在dalvik中,GC的类型有三种:

1、GC_EXPLICIT:

应用主动调用System.gc()产生的GC事件。

2、GC_FOR_ALLOC:

3、GC_CONCURRENT:

给Java层的class分配内存后,计算已分配的大小达到阈值(当前DVM heap size小一点)时会触发的GC事件。

因为第2和第3中GC是由系统触发的,所以应用是无法减少这两种类型的GC事件。但需要减少这两种GC事件是,可以通过配置dalvik的系统属性或者修改dalvik的GC算法来实现,本文只对修改dalvik的系统属性的方式进行介绍。

dalvik与GC相关的属性有:

-dalvik.vm.heapstartsize

堆分配的初始大小,调整这个值会影响到应用的流畅性和整体ram消耗。这个值越小,系统ram消耗越慢, 但是由于初始值较小,一些较大的应用需要扩张这个堆,从而引发gc和堆调整的策略,会应用反应更慢。

相反,这个值越大系统ram消耗越快,但是程序更流畅。

-dalvik.vm.heapgrowthlimit

受控情况下的极限堆(仅仅针对dalvik堆,不包括native堆)大小,dvm heap是可增长的,但是正常情况下 dvm heap的大小是不会超过dalvik.vm.heapgrowthlimit的值(非正常情况下面会详细说明)。这个值控制那

些受控应用的极限堆大小,如果受控的应用dvm heap size超过该值,则将引发oom(out of memory)。

-dalvik.vm.heapsize

不受控情况下的极限堆大小,这个就是堆的最大值。不管它是不是受控的。这个值会影响非受控应用的dalvik heap size。一旦dalvik heap size超过这个值,直接引发oom。

在android开发中,如果要使用大堆。需要在manifest中指定**android:largeHeap为true。这样dvm

heap最大可达dalvik.vm.heapsize。否则则为dalvik.vm.heapgrowthlimit **

dalvik.vm.heaputilization、dalvik.vm.heapminfree、dalvik.vm.heapmaxfree

dalvik GC时使用的参数。

贴一个发生GC_CONCURRENT 时的打印:

D/dalvikvm( 3530): GC_CONCURRENT freed 506K, 27% free 1843K/2496K,

paused 0ms+1ms, total 9ms freed 199K表示本次垃圾收集释放了199K的内存,

27% free 1843K/2496K,,其中2496K表示当前内存总量,1843K表示已用内存,27%表示可用内存占总内存的比例。

paused 0ms+1ms,第一个时间值表示markrootset的时间,第二个时间值表示第二次mark的时间。如果触发原因不是GC_CONCURRENT,这一行为单个时间值,表示垃圾收集的耗时时间。

dalvim GC策略是:

1.在一次GC后,根据当前Heap中已分配的内存大小除以dalvik.vm.heaputilization(0.75),得到一个目标值。

2.如果目标值不在(已分配的值+dalvik.vm.heapminfree)到(已分配的值+dalvik.vm.heapmaxfree)这个区间,即取区间边界值做为目标值(运行一段时间后第1步得到的目标值肯定会超过这个范围)。

3.虚拟机记录这个目标值,当做当前允许总的可以分配到的内存。同时根据目标值减去固定值(200~500K),当做触发GC_CONCURRENT事件的阈值。

4.当下一次分配内存,分配成功时。重新计算已分配的内存大小;若有达到GC_CONCURRENT的阈值,则产生GC。

5.当下一次分配内存,开始分配失败时。则会产生GC_FOR_ALLOC事件,释放内存;然后再尝试分配。

可以通过调整dalvik.vm.heapminfree 和dalvik.vm.heapmaxfree属性的值,减少GC_FOR_ALLOC和GC_CONCURRENT的次数,如果这两个值设置的过大,则会导致一次GC的时间过长,从而会看到明显的卡顿现象,设置的值既要使GC的次数减少,也不能是一次GC的时间过长。

在有的平台上,可以通过代码对单个应用的dalvik的属性进行设置,以减少对全局设置对系统的影响,可以再App里面通过如下的方式对当前的App的dalvik属性设置:

import dalvik.system.VMRuntime;

import android.os.SystemProperties;

...

VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);

VMRuntime.getRuntime().setTargetHeapMinFree(2*1024*1024);

VMRuntime.getRuntime().setTargetHeapConcurrentStart(8*1024*1024);

...

如果想通过系统进行控制,也可以在framework里面的ActivityThread的handleBindApplication函数里面进行设置:

import dalvik.system.VMRuntime;

import android.os.SystemProperties;

import java.lang.*;

...

if( data.processName.equals("com.android.launcher")) {

VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);

VMRuntime.getRuntime().setTargetHeapMinFree(2*1024*1024);

VMRuntime.getRuntime().setTargetHeapConcurrentStart(8*1024*1024);

}

...

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐