G1垃圾收集器之SATB

对象漏标

垃圾回收的并发标记阶段,GC线程和应用线程是并发执行的,所以一个对象被标记之后,应用线程可能篡改对象的引用关系,从而造成对象的漏标、误标,其实误标没什么关系,顶多造成浮动垃圾,在下次GC还是可以回收的,但是漏标的后果是致命的,把本应该存活的对象给回收了,从而影响了程序的正确性。

为了解决在并发标记过程中,存活对象漏标的情况,GC HandBook把对象分成三种颜色:
1、黑色:自身以及可达对象都已经被标记。
2、灰色:自身被标记,可达对象还未标记。
3、白色:还未被标记

所以,漏标的情况只会发生在白色对象中,且满足以下任意一个条件:
1、并发标记时,应用线程给一个黑色对象的引用类型字段赋值了该白色对象。
2、并发标记时,应用线程删除所有灰色对象到该白色对象的引用。

对于第一种情况,利用post-write barrier,记录所有新增的引用关系,然后根据这些引用关系为根重新扫描一遍。

对于第二种情况,利用pre-write barrier,将所有即将被删除的引用关系的旧引用记录下来,最后以这些旧引用为根重新扫描一边。

SATB

SATB全程snapshot-at-the-beginning,由Taiichi Yuasa为增量式标记清除垃圾收集器开发的一个算法,主要应用于垃圾收集的并发标记阶段,解决了CMS垃圾收集器重新标记阶段长时间STW的潜在风险。

Region包含了5个指针,分别是bottom、previous TAMS、next TAMS、top和end,

在这里插入图片描述

其中previous TAMS、next TAMS是前后两次发生并发标记时的位置,全程top-at-mark-start,
1、假设第n轮并发标记开始,将该Region当前的top指针赋给next TAMS,在并发标记标记期间,分配的对象都在[next TAMS,top]之间,SATB能够确保这部分的对象都会被标记,默认都是存活的。
2、当并发标记结束时,将next TAMS所在的地址赋给previous TAMS,SATB给[bottom,previous TAMS]之间的对象创建一个快照Bitmap,所有垃圾对象能通过快照被识别出来。
3、第n+1轮并发标记开始,过程和第n轮一样

SATB保证了在并发标记过程中新分配对象不会漏标
但是如果在TAMS某黑色对象B新引用该白色对象W,然后灰色对象G取消对该白色对象W的引用?

G1中如何解决?

在引用关系被修改之前,插入一层 pre-write barrier
在这里插入图片描述
pre-write barrier最终执行逻辑:
在这里插入图片描述
通过G1SATBCardTableModRefBS::enqueue(oop pre_val)把原引用保存到satb mark queue中,和RSet的实现类似,每个应用线程都自带一个satb mark queue.
在下一次的并发标记阶段,会依次处理satb mark queue中的对象,确保这部分对象在本轮GC是存活的。

原文:https://www.jianshu.com/p/9e70097807ba

猜你喜欢

转载自blog.csdn.net/f191501223/article/details/84726719
今日推荐