Android Dalvik VM内存优化之内存泄露篇。

来源:互联网 发布:淘宝ar怎么用 编辑:程序博客网 时间:2024/06/10 21:18
Android Dalvik VM内存优化之内存泄露篇。

虽然Dalvik VM支持垃圾收集,但是这不意味着可以不用关心内存管理。其实更应该格外注意移动设备的内存使用,毕竟其内存空间是受到限制的。在实际应用中,一些内存使用问题是很明显的,例如在每次用户触摸屏幕的时候如果应用程序有内存泄露,将会有可能触发OutOfMemoryError,最终会导致程序崩溃。另外一些问题却很微妙,也许知识降低应用程序和整个系统的性能(当高频率和长时间地运行垃圾收集器的时候)。

本篇目录:
1、什么是内存泄露。
2、为什么会发生内存泄露。
3、GC 如何回收对象?
4、shallow size、retained size。
5、查看Android内存泄露的工具-------MAT。

1、什么是内存泄露:

内存泄露指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄露并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段的内存的控制,从而造成了内存的浪费。内存泄露会因为减少可用内存的数量从而导致程序的性能降低。最终,在最糟糕的情况下,过多的可用内存被分配掉,导致全部或部分的设备停止正常工作,或则应用程序崩溃。

2、为什么会发生内存泄露:

2.1:Generation(代):
JVM会根据generation(代)来进行GC,一共分为:
1、Young Generation(新生代),
2、Tenured Generation(年老代),
3、Permanent Generation(永久代,Perm Gen)
【Perm Gen或称Non-Heap非堆。注意:Heap空间不包括Perm Gen.】

2.2:绝大多数的对象都在Yount Generation被分配,也在Young Generation被回收。当Young Generation的空间被填满时,GC 会进行Minor Collection(次回收),这样子的次回收不涉及Heap中其他的Generation。Minor Collection会根据Weak Generation(弱年代)来假设Young Generation 中大量的对象都是垃圾需要回收,Minor Collection 的过程会非常快。在 Young Generation 中,没有被回收的对象被转移到Tenured Generation,然而Tenured Generation也会被填满,最终触发Major Collection(主回收),这次回收针对整个Heap,由于设计大量对象,所以比Minor Collection 慢得多。
由于Tenured Generation 的 Major Collection过程比较慢,所以如果 Tenured Generation 空间小于 Young Generation,会造成频繁的 Major Collection,会影响效率。Server JVM默认的 Young Generation 和 Tenured Generation 空间比例为 1:2,也就是说Young Generation 的 Eden 和 Survivor 空间之和时整个Heap (当然不包括 perm gen)的 1/3 , 该比例可以通过-XX:NewRatio = n 参数来控制,而Client JVM 默认的 -XX:NewRatio 是 8 。
Young Generation 中幸存的对象被转移到Tenured Generation,但是Concurrent Collection 线程在这里进行Major Collection,而在回收任务结束之前空间被耗尽了,这时将会发生 Full Collections(Full GC),整个应用都会停止下来知道回收完成。由此可见,Full GC 是高负载生产环境的噩梦。
Perm Gen,它是JVM用来存储无法在Java语言级描述的对象,这些对象分别是类和方法数据(与class loader有关)以及interned strings(字符串驻留)。一般32位OS下的Perm Gen默认64MB, 可通过参数 -XX:MaxPermSize = n 指定。

3、GC 如何回收对象?

当然是GC发现通过任何 reference chain(引用链)无法访问某个对象的时候,改对象即被回收。例如JVM自己确保了对象的可到达性(那么JVM就是GC Roots),所以GC Roots 就是这样在内存中保持对象可到达性的,一旦不可到达,即被回收。

引用级别:

1、Strong Ref(强引用):通常编写的代码都是Strong Ref,与此对应的是强可达性,只有去掉强可达,对象才会回收。
2、Soft Ref(软引用):只要有足够的内存,就一直保持对象,知道发现内存吃紧且没有Strong Ref时才会收对象。一般可用来实现缓存。
3、Weak Ref (弱引用):当发现不存在Strong Ref 时,立刻回收对象而不必等到内存吃紧的时候。
4、Phantom Ref(虚引用):根本不会在内存中保持任何对象,只能使用Phantom Ref 本身。一般用于在进入finalize()方法后进行特殊的清理过程。

4、shallow size、retained size。

shallow Size 是指对象本身占用内存的大小,不包含对其他对象的引用,也就是对象头加成员变量(不是成员变量的值)的总和。

retained Size 是指该对象自己的 shallow size ,加上从该对象能直接或间接访问到对象的shallow size 之和。换句话说,retained size 是指对象被 GC 之后 所能回收到内存的总和。


5、查看Android内存泄露的工具---------MAT:

MAT 是 Memory Analyzer Tool 的缩写。
在开发应用过程中,可以使用现成的工具来查看内存泄露情况。

MAT大部分功能:
1、Histogram : 可以列出内存中的对象、对象的个数以及大小。
2、Dominator Tree:可以列出那个线程,以及线程下面的那些对象占用的空间。
3、Top consumers:通过图形列出最大的 object。
4、Leak Suspect :通过MA 自动分析泄露的原因。





原创粉丝点击