炸了!一口气问了我18个JVM问题! (3)

而并行 full GC 虽然有一个 ParallelOld,但却与 CMS GC 不兼容所以无法作为它的备份 full GC使用。

为什么有些新老年代的收集器不能组合使用比如 ParNew 和 Parallel Old?

炸了!一口气问了我18个JVM问题!

这张图是 2008 年 HostSpot 一位 GC 组成员画的,那时候 G1 还没问世,在研发中,所以画了个问号在上面。

里面的回答是 :

"ParNew" is written in a style... "Parallel Old" is not written in the "ParNew" style

HotSpot VM 自身的分代收集器实现有一套框架,只有在框架内的实现才能互相搭配使用。

而有个开发他不想按照这个框架实现,自己写了个,测试的成绩还不错后来被 HotSpot VM 给吸收了,这就导致了不兼容。

我之前看到一个回答解释的很形象:就像动车组车头带不了绿皮车厢一样,电气,挂钩啥的都不匹配。

新生代的 GC 如何避免全堆扫描?

在常见的分代 GC 中就是利用记忆集来实现的,记录可能存在的老年代中有新生代的引用的对象地址,来避免全堆扫描。

炸了!一口气问了我18个JVM问题!

上图有个对象精度的,一个是卡精度的,卡精度的叫卡表。

把堆中分为很多块,每块 512 字节(卡页),用字节数组来中的一个元素来表示某一块,1表示脏块,里面存在跨代引用。

炸了!一口气问了我18个JVM问题!

在 Hotspot 中的实现是卡表,是通过写后屏障维护的,伪代码如下。

炸了!一口气问了我18个JVM问题!

cms 中需要记录老年代指向年轻代的引用,但是写屏障的实现并没有做任何条件的过滤

不判断当前对象是老年代对象且引用的是新生代对象才会标记对应的卡表为脏。

只要是引用赋值都会把对象的卡标记为脏,当然YGC扫描的时候只会扫老年代的卡表。

这样做是减少写屏障带来的消耗,毕竟引用的赋值非常的频繁。

那 cms 的记忆集和 G1 的记忆集有什么不一样?

cms 的记忆集的实现是卡表即 card table。

通常实现的记忆集是 points-out 的,我们知道记忆集是用来记录非收集区域指向收集区域的跨代引用,它的主语其实是非收集区域,所以是 points-out 的。

在 cms 中只有老年代指向年轻代的卡表,用于年轻代 gc。

而 G1 是基于 region 的,所以在 points-out 的卡表之上还加了个 points-into 的结构。

因为一个 region 需要知道有哪些别的 region 有指向自己的指针,然后还需要知道这些指针在哪些 card 中

其实 G1 的记忆集就是个 hash table,key 就是别的 region 的起始地址,然后 value 是一个集合,里面存储这 card table 的 index。

我们来看下这个图就很清晰了。

炸了!一口气问了我18个JVM问题!

像每次引用字段的赋值都需要维护记忆集开销很大,所以 G1 的实现利用了 logging write barrier(下文会介绍)。

也是异步思想,会先将修改记录到队列中,当队列超过一定阈值由后台线程取出遍历来更新记忆集。

为什么 G1 不维护年轻代到老年代的记忆集?

G1 分了 young GC 和 mixed gc。

young gc 会选取所有年轻代的 region 进行收集。

midex gc 会选取所有年轻代的 region 和一些收集收益高的老年代 region 进行收集。

所以年轻代的 region 都在收集范围内,所以不需要额外记录年轻代到老年代的跨代引用

cms 和 G1 为了维持并发的正确性分别用了什么手段?

之前文章分析到了并发执行漏标的两个充分必要条件是:

将新对象插入已扫描完毕的对象中,即插入黑色对象到白色对象的引用。

删除了灰色对象到白色对象的引用。

cms 和 g1 分别通过增量更新和 SATB 来打破这两个充分必要条件,维持了 GC 线程与应用线程并发的正确性。

cms 用了增量更新(Incremental update),打破了第一个条件,通过写屏障将插入的白色对象标记成灰色,即加入到标记栈中,在 remark 阶段再扫描,防止漏标情况。

G1 用了 SATB(snapshot-at-the-beginning),打破了第二个条件,会通过写屏障把旧的引用关系记下来,之后再把旧引用关系再扫描过。

这个从英文名词来看就已经很清晰了。讲白了就是在 GC 开始时候如果对象是存活的就认为其存活,等于拍了个快照。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxpzg.html