简介
Android art对app内存具体怎么控制?初浅的理解为两方面,一方面是最大调控要求多少,一方面是过程调控怎么分析。对于最大调控,由heapgrowthlimit/heapsize值决定,此部分容易理解,app内存超过最大值发生OOM;对于过程调控,由heapmaxfree、heapminfree、heaptargetutilization联合决定,此部分简单理解为:art分配app的内存由两部分组成=已使用的内存+预留的内存,对于预留内存的大小,则由heapmaxfree、heapminfree、heaptargetutilization联合控制,当app立马需要分配大内存(超过了预留内存大小)时,自然需要进行gc清理,此时便涉及内存抖动。
当然app发生oom,除了java堆之外,有其他例如native堆等等,对于native情况,相对比较复杂,这里不作介绍。
关键属性分析
注:
可参考:
Android之ART App内存回收机制整理 学习
dalvik.vm.heapgrowthlimit
默认dalvik虚拟机最大内存为dalvik.vm.heapgrowthlimit
dalvik.vm.heapsize
当应用的AndroidManifest.xml中导入android:largeHeap=true,则采用dalvik.vm.heapsize值
dalvik.vm.heapstartsize
app初始分布内存大小
dalvik.vm.heapmaxfree
预留最大空间的参考值
dalvik.vm.heapminfree
预留最小空间的参考值
dalvik.vm.heaptargetutilization
堆利用率
举例:
app内存=app已使用+预留内存
2*heapminfree <= 预留空间 <= 2*heapmaxfree
修改建议
1.dalvik.vm.heapmaxfree 当频繁发现发生gc时,可考虑把heapmaxfree值调大
2.为了保证app正常快速运行,可考虑增大如下属性值
dalvik.vm.heapgrowthlimit
dalvik.vm.heapsize
api接口
ActivityManager.getMemoryClass() - dalvik.vm.heapgrowthlimit值
ActivityManager.getLargeMemoryClass() - dalvik.vm.heapsize值
ActivityManager.MemoryInfo.availMem - 系统可用内存大小
ActivityManager.MemoryInfo.lowMemory - 系统是否处于低内存状态
ActivityManager.MemoryInfo.threshold - 系统availMem低于这个值时认为处理lowMemory状态
ActivityManager.MemoryInfo.totalMem - 系统总内存大小
Runtime.totalMemory() - 当前 VM 的 heap 大小
Runtime.maxMemory() - 当前 VM 的 heap 上限值,即 getMemoryClass() 或 getLargeMemoryClass() 的返回值
Runtime.freeMemory() - 当前 VM 的 heap 中可用内存大小
工具
代码端监控内存oom工具
leakcanary
学习网址
https://blog.csdn.net/noblef/article/details/108975861
https://juejin.cn/post/6844903762658590728#heading-1
https://github.com/square/leakcanary
分析工具
Android Studio
Profiler -- Memory
学校网址:
https://developer.android.com/studio/profile/memory-profiler?hl=zh-cn#save-hprof
发生art gc的日志分析
注:
oom发生时 可通过adb bugreport获取日志
查看logcat日志,例如:
art : Explicit concurrent mark sweep GC freed 3550(178KB) AllocSpace objects, 0(0B) LOS objects, 39% free, 3MB/6MB, paused 149us total 11.494ms
格式如下:
art : <GC_Reason> <GC_Name> <Objects_freed>(<Size_freed>) AllocSpace Objects, <Large_objects_freed>(<Large_object_size_freed>) <Heap_stats> LOS objects, <Pause_time(s)>
详解:
<GC_Reason> 触发垃圾回收的原因以及触发了何种类型的垃圾回收,它包含以下几类:
Concurrent 特点是不需要挂起应用线程。它在后台线程中运行,不会影响到内存的分配。
Alloc 它在应用申请内存但是堆已满的情况下触发。在这种情况下,垃圾回收在分配内存的线程中进行。(它会导致应用暂停一段时间)
Explicit 主动发起的垃圾回收,例如System.gc()。跟dalvik一样,建议不要主动发起垃圾回收。
NativeAlloc 它会在native层内存吃紧的时候发起。比如说分配Bitmap或者RenderScript内存空间不够的时候。
CollectorTransition 一般由堆转换引起,垃圾回收器会把free-list back空间的所有对象都复制到bump pointer空间中。目前,转换过程只在一些低内存的设备上应用所在进程从对暂停敏感切换到对暂停不敏感状态的时候发生。
HomogeneousSpaceCompact 它是在free-list 空间到free-list空间的复制。当app所在进程对暂停不敏感的时候发生。它可以减少内存的使用,减少内存分配的碎片化。
DisableMovingGc 它并不是引起内存回收的真正原因,它是垃圾回收被GetPrimitiveCritical中断时发生的。当concurrent 堆压缩正在执行的时候,因为对垃圾回收器的限制,所以非常不建议使用它。
HeapTrim 它不是触发垃圾回收的原因,但是在堆压缩的时候垃圾回收会被终止。
<GC Name> 垃圾回收的名称,一共有如下几类:
Concurrent mark sweep(CMS) 对整个堆进行垃圾回收,除了image空间。
Concurrent partial mark sweep 对几乎整个堆进行回收,除了image空间和zynote空间。
Concurrent sticky mark sweep 一次普通的垃圾回收,它只负责回收上次垃圾回收之后的分配的对象。它要比Concurrent partial mark sweep执行的次数频繁的多,因为它的执行速度快,暂停时间少。
Marksweep + semispace 一种非同时进行的,包含复制过程的GC。可以用来移动堆,也可以用来压缩堆(减少堆的碎片化)。
<Objects freed> 释放了对象(非大对象)的数量
<Size freed> 释放了空间(非大对象)的大小
<Large objects freed> 释放了大对象的数量
<Large object size freed> 释放了大对象的空间的大小
<Heap stats> 堆中空闲空间的百分比 和 (对象的个数)/(堆的总空间)
<Pause times> 一般情况下,垃圾回收的暂停时间跟堆中引用的数量成正比。目前,ART CMS GC 只有一次在垃圾回收结束的时候。内存转移的GC在整个过程中有一个长时间的暂停。
系统代码
aops/art
参考学习
https://www.jianshu.com/p/3c3ad793e7e2
https://www.jianshu.com/p/fba7b43bdc9c
https://jsonchao.github.io/
https://wuyifei.cc/android-oom/
https://cloud.tencent.com/developer/article/1004843
网友评论