Android Dalvik虚拟机内存分配问题
2017-03-09 17:07
435 查看
之前遇到一个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。
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。
相关文章推荐
- Android Dalvik虚拟机内存分配问题
- Android Dalvik虚拟机内存分配问题
- Android Dalvik虚拟机内存分配问题
- Android Dalvik虚拟机内存分配问题
- Android虚拟机(DVM)内存分配——内存溢出问题
- Android虚拟机(DVM)内存分配——内存溢出问题
- Android虚拟机(DVM)内存分配——内存溢出问题
- Android虚拟机(DVM)内存分配——内存溢出问题
- Android虚拟机(DVM)内存分配——内存溢出问题
- 【昊昊带你学】android-解决/data/dalvik-cache占用内存的问题
- Android_对android虚拟机的理解,包括内存管理机制垃圾回收机制。dalvik和art区别
- Android有效解决加载大图片内存溢出问题及优化虚拟机内存
- 从java内存分配角度分析android内存泄漏问题
- 小白请教几个关于Java虚拟机内存分配策略的问题
- Android -- android app 能分配的最大内存堆栈问题
- Android学习札记25:对Android虚拟机(DVM)内存分配的一些理解
- Android有效解决加载大图片内存溢出问题及优化虚拟机内存
- Dalvik虚拟机为新创建对象分配内存的过程分析
- 深入理解Android虚拟机三------内存分配策略
- 计算dalvik虚拟机剩余可分配内存