Android 的GC机制
主动触发GC:adb shell kill -10 pid
以下总结了几个思考的角度:
1. 角度1 ----》对象引用
强引用、软引用、弱引用、虚引用,java中对象的四种引用方式
- 强引用 不回收
只要某个对象有强引用与之关联,JVM必定不会回收这个对象。
即使内存不足,JVM宁愿抛出OutOfMemory错误也不会回收这种对象 - 软引用 内存不足回收
用来描述一些有用但并不是必须的对象。
对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象。 - 弱引用 有GC操作就回收
弱引用是用来描述非必须的对象。
当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。 - 虚引用 相当于没有引用
不影响对象的生命周期。
如果一个对象与虚引用关联,则跟没有引用与之关联一样。
在任何时候都可能被垃圾回收器回收。
问题:如何通过工具查看,对象的引用情况?
2. 角度2 —》 常见GC
GC_OR_ALLOC 分配内存但堆内存不足时
新建的java对象,一般分配在 堆内存中(GC中的 free项)
当堆内存剩余空间不够新建该java对象时,触发此类GC
GC_EXPLICIT 显式GC(如主动调用System.gc()方法、一个线程被杀死、一个连接被停止 )
是唯一一种有用的可以人为控制触发时机的GC。
可在合适的时机(如用户无明显感知的时机)主动触发GC,以减少其他类型GC的出现次数
GC_CONCURRENT 堆对象数多导致的短时并发GC
并发GC,在应用程序继续运行的同时进行的,堆中的对象数量达到一定程度触发的垃圾回收。
一般时间较短,用户不会有明显感知。
但是出现的太频繁说明内存中对象数量增长太快
GC_EXTERNAL_ALLOC 堆以外的内存使用量达到一定阈值时
虚拟机尝试减少用于可回收对象的总的内存空间,为更多的不可回收对象挪地方
GC_HPROF_DUMP_HEAP 不关注
从DDMS打出某个进程堆信息时会触发此GC,正常系统不会自动触发,不需要关注
问题1:如何查看是否发生GC,以及发生的是什么GC?
答:打开GC日志,能看到GC的类型。操作变量为:kLogAllGCs
问题2:多次提到阈值,堆的阈值是多少,堆之外的呢?创建对象内存不足是分配失败吗?
adb shell getprop | grep dalvik.vm.heap
关注的阈值:
-
dalvik.vm.heapgrowthlimit
应用堆最大可用内存值 -
dalvik.vm.heapmaxfree
堆最大空闲内存
当前dlmalloc管理的内存最多可以有的free memory -
dalvik.vm.heapminfree
堆最小空闲内存
当前dlmalloc管理的内存最少需要的free memory -
dalvik.vm.heapsize
应用最大可用的堆内存。应用Manifest中配置android:largeHeap="true"时,最大堆内存大小就可使用dalvik.vm.heapsize的值 -
dalvik.vm.heapstartsize
堆分配的初始值大小,这个值越小,系统内存消耗越慢,但是当应用扩展这个堆,导致 GC 和堆调整时,应用会变慢 -
dalvik.vm.heaptargetutilization
内存的利用率。dlmalloc管理的内存的理想的使用率(malloc_size / cur_heap_size )
每次GC之后会评估当前堆内存的大小是否是适合的