并发标记(Concurrent Marking)
先看前面引用的书中描述:
并发标记(Concurrent Marking):从 GC Roots 开始对堆的对象进行可达性分析,递归扫描整个堆里的对象图,找出存活的对象,这阶段耗时较长,但是可以与用户程序并发执行。当对象图扫描完成以后,还要重新处理 SATB 记录下的在并发时有引用变动的对象。
再看动图:
从 GC Roots 开始对堆的对象进行可达性分析,递归扫描整个堆里的对象图,找出存活的对象:
意思就是说在并发标记阶段, GC 线程工作在 prevTAMS 和 NextTAMS 之间,对堆里的对象进行可达性分析(回想一下“三色标记”),标记完成后, NextBitmap 就有对应有值了(里面放的是地址值),黑色对应的是存活对象,白色对应的垃圾对象。
这样就找出存活对象了。
但是书中并没有提及用户线程分配对象的情况。所以读者提出的问题,在书中也找不到明确的答案。
答案就是: NextTAMS 与 Top 之间的对象,就是本次并发标记阶段用户线程新分配的对象,它们是隐式存活的。
为什么这么说?你去品一品论文里面我框起来的这句话。
但是面试官想要的是这一句话的答案吗?不是的。
你听到这个问题后,你先微微一皱眉,做出沉思状,然后轻轻说说一句:这个问题问的很好,我先组织一下语言。(先舔他一波)
然后你按照阶段把图画出来,指着给他讲 TAMS 和 Bitmap 是怎么工作的。
另外,关于 NextTAMS 与 Top 为什么是重叠的,也得补充说明一下:并发标记的前一个阶段是初始标记。由于初始标记是 STW 的,所以从动图中我们可以看到:并发标记开始,即初始标记结束的时候, NextTAMS 与 Top 是重叠的。
随着并发标记过程的进行, NextBitmap 被填充上了值。而 NextTAMS 与 Top 之间的区域越来越大,这就是用户线程在并发标记阶段分配的新对象。
同时通过下面的图我们可以看到, GC 线程的工作区间和用户线程的工作区间是有重叠的(用工作区间这个概念去理解其中的一些细节不一定正确,但是可以这样抽象的认为,方便理解)。
而重叠的部分,就是可能产生“对象消失”的部分。对G1来说,就是原始快照(STAB)加写前屏障(Pre-Wirte Barrier)工作的部分。
所以这就是书里为什么说:当 GC 线程扫描完对象图后,还需要重新处理 STAB 记录下的在并发时有引用变动的对象。
最终标记(Remark)
书中是这样的写的:
最终标记(Final Marking):对用户线程做另一个短暂的暂停,用于处理并发阶段结束后仍遗留下来的最后那少量的 SATB 记录
最终标记阶段,由于是 STW 的,所以该阶段对应的图是并发标记阶段完成后的图,如下:
处理并发阶段结束后仍遗留下来的最后那少量的 SATB 记录是什么意思呢?
你想,并发标记阶段, GC 线程完成对象图的扫描之后,还会去处理 SATB 记录下的在并发时有引用变动的对象。
在处理 SATB 记录的数据的时候,由于用户线程可能还是在继续修改对象图,继续在产生 SATB 数据,所以还是会有一小部分的 SATB 数据,所以才需要一个短暂的暂停。
清理阶段(Cleanup)
书里写的是筛选回收阶段。其实就包含了清理阶段和回收阶段。这里我们只讨论清理阶段,不讨论回收。
在这个阶段, NextBitmap 和 PrevBitmap 会交换位置:
所以,我们的图就变成了下面的样子:
可以看到,NextBitmap 和 PrevBitmap 交换了位置,NextTAMS 和 PrevTAMS 交换了位置。
而 Region 中, Bitmap 白色部分对应的已使用内存变成了浅灰色。它仅仅是标记了出来,并没有进行清扫操作。
需要注意的是:清理阶段不拷贝任何对象
引用R大的回答来描述这个阶段:
清点和重置标记状态。这个阶段有点像 mark-sweep 中的 sweep 阶段,不过不是在堆上 sweep 实际对象,而是在 marking bitmap 里统计每个 Region 被标记为活的对象有多少。这个阶段如果发现完全没有活对象的 Region 就会将其整体回收到可分配 Region 列表中。
好了,到这里我们就能把前面的那张图给填上了:
然后再看一下论文中的这张图片,你就会发现,我上面的过程都是基于这张图片去分析的,图中展示了两个循环, A-B-C , D-E-F 。其中 E、F 过程就是 B、C 过程的重复:
我让上面的图片动起来,请细细品。请注意各个阶段 PrevTAMS 、 NextTAMS 指针的交换、 PrevBitmap 和 NextBitmap 位置的交换:
如果一次看不懂,就再看一次。看的时候结合上面的长图和动图一起分析,效果更佳。
参考资料:
1.https://max.book118.com/html/2018/0815/7043143036001143.shtm
2.https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/G1GettingStarted/index.html
3.https://www.oracle.com/technetwork/java/javase/tech/g1-intro-jsp-135488.html
4.https://www.infoq.com/articles/G1-One-Garbage-Collector-To-Rule-Them-All/
5.https://hllvm-group.iteye.com/group/topic/44381
6.《深入理解Java虚拟机(第三版)》
最后说一句(求关注)
本文是对《面试官:你说你熟悉jvm?那你讲一下并发的可达性分析》这篇文章的补充说明。如果你没看过,我建议你去看看。
我觉得有些知识点仅仅靠文章和图片是很难说清楚的,所以我费劲的做了动图。
为了做这篇文章和上篇文章中的几张动图,加起来我截了 80 多张图。你知道我为了把每张图截的一个像素都不差,我有多努力吗?
截的我眼球布满了血丝,眼睛都快瞎了,你不关注一波?
我四级半的英语水平,为了文章的正确性,强行啃英文论文,你不感动吗?
点个关注呀,别白嫖我啊,大哥。写文章很辛苦的,需要来点正反馈。
才疏学浅,难免会有纰漏,如果你发现了错误的地方,还请你留言给我指出来,我对其加以修改。
感谢您的阅读,我坚持原创,十分欢迎并感谢您的关注。
我是why技术,一个不是大佬,但是喜欢分享,又暖又有料的四川好男人。
以上。
欢迎关注公众号【why技术】,坚持输出原创。分享技术、品味生活,愿你我共同进步。