GC系统

GC系统遵循GC Root搜索算法,根据是否包含其他对象的引用来判断是否需要进行GC。在Android 2.3之前,GC是同步发生的,而且是一次完整的Heap遍历。也就是说,每次GC都会打断应用的正常运行,而且应用占用内存越大,GC时间越长。而在Android 2.3之后,系统修改了GC,将GC作为并发线程,同时每次GC并不会遍历整个Heap,而是只遍历一部分内存。

GC系统 - 图1这里的GC同步与非同步是指:在Android 2.3之前的版本,GC是会打断被GC的线程的,而Android 2.3之后的版本,GC与被GC线程可以同时工作而互不影响。

这是GC算法的第一次提升,一直到Android 4.4都没有发生大的改变,直到Android 5.0的到来。在Android 5.0之前,GC一直扮演着一个清理工的角色,GC打断进程,遍历Heap,清理垃圾。但是在清理的过程中,没有对内存碎片进行整理,这就导致当系统进行了大量GC后,内存碎片越来越多,完整的内存区域越来越少。即使整个碎片加起来有10MB,但完整的一个连续内存区域却可能只有1MB。这就导致了OOM,即使此时你还有很多内存。因此在Android 5.0之后,系统第二次优化了GC,加快了GC的清理速度,减少了打断进程的次数。同时GC不仅扮演清理工的角色,还扮演了一个管家的角色,它可以为大内存对象分配特殊的地址,方便内存碎片的整理。当你的应用在后台运行后,GC系统会对整个App的内存进行对齐,将小的内存碎片清理出来,构成完整的内存区域,从而提高内存的使用率。

GC系统根据GC Root算法进行GC工作,该算法会以一个GC Root对象为起点,搜索与之相关联的对象。如果某个对象与GC Root对象没有找到引用链,则表示该对象需要进行回收,常见的GCRoot对象有以下几种。

  • class:由System class loader加载的对象。
  • JNI:jni相关调用的引用、变量、参数。
  • Thread:活着的线程。
  • Stack:栈中的对象。
  • 静态:方法区类的静态属性引用的对象。
  • 常量:方法区中的常量引用的对象(final类型)。