之前遇到一个Android上图片加载不出来的问题,在三星的note3上极容易出现,而在nexus 4上则很难出现。后来通过DDMS观察发现,是某一个模块一直内存泄漏使得内存接近上限,导致一些大图(需要的内存比较大)申请内存失败,一直加载不出来。为什么会出现这种状况呢?

      通过getprop拿到两个手机上dalvik虚拟机的参数,三星的note3上的dalvik.vm.heapgrowthlimit为64M,而nexus4上的dalvik.vm.heapgrowthlimit为192M,后者是前者的三倍。也就是说note3上存在内存泄漏的时候,虚拟机的内存很容易就达到64M的上限,而在nexus4上要达到192M还是很难的,这也就解释了前面的现象。

      说到这里,我们来看看虚拟机的几个重要参数的意义。

      dalvik.vm.heapstartsize  

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

     dalvik.vm.heapgrowthlimit       

     极限堆大小,dvm heap是可增长的,但是正常情况下dvm heap的大小是不会超过dalvik.vm.heapgrowthlimit的值。如果受控的应用dvm heap size超过该值,则将引发oom。

    dalvik.vm.heapsize 

    使用大堆时,极限堆大小。一旦dalvik heap size超过这个值,直接引发oom。在android开发中,如果要使用大堆,需要在manifest中指定android:largeHeap为true。这样dvm heap最大可达dalvik.vm.heapsize。

    [dalvik.vm.heaptargetutilization]: [0.75]   可以设定内存利用率的百分比,当实际的利用率偏离这个百分比的时候,虚拟机会在GC的时候调整堆内存大小,让实际占用率向个百分比靠拢。


   上面的几个参数是与虚拟机的内存分配相关的,虚拟机的内存分配过程是下面这样的:

1  首先判断一下需要申请的size是不是过大,如果申请的size超过了堆的最大限制,则转入步骤6

2  尝试分配,如果成功则返回,失败则转入步骤3

3  判断是否gc正在进行垃圾回收,如果正在进行则等待回收完成之后,尝试分配。如果成功则返回,失败则转入步骤4

4  自己启动gc进行垃圾回收,这里gcForMalloc的参数是false。所以不会回收软引用,回收完成后尝试分配,如果成功则返回,失败则转入步骤5

5  调用dvmHeapSourceAllocAndGrow尝试分配,这个函数会扩张堆。所以heap startup的时候可以给一个比较小的初始堆,实在不够用再调用它进行扩张

6  进入回收软引用阶段,这里gcForMalloc的参数是ture,所以需要回收软引用。然后调用dvmHeapSourceAllocAndGrow尝试分配,如果失败则抛出OOM。














Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐