引言:G1垃圾收集器创造性地把堆空间分为若干个区域(Region),通过选定CSet的方式来控制垃圾回收的区域,可以较为精确控制垃圾回收的效益和成本,此外,G1垃圾收集器在整体上采用标记-整理的方式,加大了吞吐量。总而言之,G1垃圾收集器是一款兼顾响应速度和吞吐量的垃圾收集器。
工作流程
1.多次 YoungGC :默认情况下进行新生代回收
2.Initial marking +YoungGC : 当堆中的垃圾达到阈值后,触发全局并发标记,全局并发标记中的初始标记阶段搭载在一次新生代回收上运行
3.Root region scanning :根扫描阶段,并发处理初始标记阶段中新生代到老年代的引用修改,这个阶段完成以后才能进行下一次YoungGC
4.Concurrent marking :并发标记阶段,遍历对象图,可以和YoungGC并行
5.Remark :重新标记阶段,处理剩余的SATB logging buffer中的引用
6.Cleanup :清理区域中对象全部需要回收的区域
7.多次 Mixed GC :全局并发标记结束后,进行多次混合回收
从整体上说,跟G1回收过程相关的后台线程可以分为两个部分,一部分是全局并发标记,对应工作流程中的2~6 ,另一部分是暂停拷贝,暂停拷贝阶段是STW的,是需要暂停全部用户线程,但是后台线程还是可以正常运行,暂停拷贝阶段分为新生代回收和混合回收,其中值得注意的是全局并发标记是为混合回收服务的。
新生代回收
以下是G1论文对Evacuation Pauses的描述:
The first step of an evacuation pause is to sequentially choose the collection set (section 3 details the mechanisms and heuristics of this choice). Next, the main parallel phase of the evacuation pause starts. GC threads compete to claim tasks such as scanning pending log buffers to update remembered sets, scanning remembered sets and other root groups for live objects, and
evacuating the live objects.
1.选定新生代Region构成CSet,扫描根集合,从根集合出发扫描新生代。
2.处理Dirty card queue 并更新Rset
3.处理Rset中老年代到新生代的引用,避免跨代指针问题。
4.把存活对象从Eden区域和From survivor区域移动到To survivor区域
混合回收
混合回收除了要完成新生代回收需要完成的事情外,还需要选定几个Old区域进入CSet,这几个Old区域中的对象存活情况由全局并发标记确定,最后把这几个Old区域中标记为存活的对象移动到新的Old区域。
总结
1.总的来说,这篇文章是对G1垃圾回收流程的梳理,其中提到的一些名词并没有详细展开,如果有不明白的地方可以在博客下方留言
2.G1垃圾收集器的内容相对复杂,如果文章中有错误的地方,欢迎大家留言帮忙指正。
参考文献
(1)G1论文地址:
https://dl.acm.org/doi/pdf/10.1145/1029873.1029879
(2)RednaxelaFX的博客:
https://hllvm-group.iteye.com/group/topic/44381
(3)Oracle官网文章
https://www.oracle.com/technical-resources/articles/java/g1gc.html