G1在进行垃圾收集的过程,会根据每个Region预计垃圾收集所需时间与预计回收内存大小的占比来选择对那些区域进行回收,也就是不再有Minor GC/Yong GC和Major GC/Full GC的概念,而是采用一种Mixed GC的方式,即混合回收的GC方式。
G1的垃圾收集(主要指Mixed GC)过程可以分为下面几个步骤:
初始标记:需要暂定所有线程,即STW,并记录下GC Roots能直接引用的对象,速度很快,与CMS的初始标记一样。
并发标记:可以与应用线程一起工作,进行可达性分析,与CMS的并发标记一样。
最终标记:需要暂停所有线程(STW),根据三色标记算法修复一些引用的状态,与CMS的重新标记是一样的。
筛选回收:筛选回收阶段会对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿STW时间(可以通过参数-XX:MaxGCPauseMills设置)来制定回收计划。
比如此时1000个Region都满了,但根据用户设置的STW时间,本次垃圾回收只能停顿200毫秒,那么通过之前的回收成本计算,200毫秒只能回收600个Region的内存空间,那么G1就会只回收这600个Region(Collection Set,要回收的集合)的内存空间,尽量把GC的停顿时间控制在用户指定的停顿时间内。
在回收的时候,使用的复制算法,将一个Region中的存活对象移动到另一个空的Region中,然后将之前的Region内存空间清空,G1就不需要像CMS那样回收完内存后很多脆片还要进行整理,采用复制算法几乎不会有内存碎片。
CMS在并发清理阶段,垃圾收集器线程是可以与用户线程一起并发执行,但G1因为内部实现太复杂就没有实现并发回收,不过到了ZGC就实现了并发收集。
在筛选回收阶段对各个Region进行回收价值和成本进行排序,如何理解?
比如现在有Region1、Region2和Region3三个区域,其中Region1预计可以回收1.5MB内存,预计耗时2ms;Region2预计可以回收1MB内存,预计耗时1ms;Region3预计可以回收0.5MB内存,预计耗时1ms。那么Region1、Region2和Region3各自的回收价值与成本比值分别是:0.75、1和0.5。
比值越高说明同样的付出,收益越高,如果此时只能回收一个Region的内存空间,G1就会选择Region2进行回收。这种方式保证了G1收集器在有限的时间内尽可能地提高收集效率。