AndroidAndroid性能优化

Android 内存泄露

2017-02-27  本文已影响9人  xsp单细胞

前言

对于 c++ 来说,内存泄漏就是new出来的对象没有 delete,俗称野指针;而对于 java 来说,就是 new 出来的 object 放在 Heap 上无法被GC回收

对象的引用方式

  • 强引用(StrongReference):new 的对象没释放,JVM 哪怕发生 OOM 错误也不会回收该对象

Java 内存

Java是在JVM所虚拟出的内存环境中运行的,JVM的内存可分为三个区:堆(heap)、栈(stack)和方法区(method)

  • 栈:栈中只存放基本类型和对象的引用(不是对象),LIFO

垃圾回收机制

垃圾回收(garbage collection,简称GC)可以自动清空堆中不再使用的对象。在JAVA中对象是通过引用使用的。如果再没有引用指向该对象,那么该对象就无从处理或调用该对象,这样的对象称为不可到达。垃圾回收用于释放不可到达的对象所占据的内存。
实现思想:我们将栈定义为root,遍历栈中所有的对象的引用,再遍历一遍堆中的对象。因为栈中的对象的引用执行完毕就删除,所以我们就可以通过栈中的对象的引用,查找到堆中没有被指向的对象,这些对象即为不可到达对象,对其进行垃圾回收。

垃圾回收机制

内存泄露 VS 内存溢出

内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用
内存泄露 (memory leak):是指程序在申请内存后,无法释放已申请的内存空间

内存泄露原因

在JAVA中JVM的栈记录了方法的调用,每个线程拥有一个栈。在线程的运行过程当中,执行到一个新的方法调用,就在栈中增加一个内存单元,即帧(frame)。在frame中,保存有该方法调用的参数、局部变量和返回地址。然而JAVA中的局部变量只能是基本类型变量(int),或者对象的引用。所以在栈中只存放基本类型变量和对象的引用。引用的对象保存在堆中
当某方法运行结束时,该方法对应的frame将会从栈中删除,frame中所有局部变量和参数所占有的空间也随之释放。线程回到原方法继续执行,当所有的栈都清空的时候,程序也就随之运行结束
而对于堆内存,堆存放着普通变量。在JAVA中堆内存不会随着方法的结束而清空,所以在方法中定义了局部变量,在方法结束后变量依然存活在堆中

常见的内存泄露

工具

上一篇下一篇

猜你喜欢

热点阅读