认识垃圾回收器-Shenandoah

164 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第 14 天,点击查看活动详情

1 前言

在前文中已经分享了 G1 和 ZGC 两款垃圾回收器,在本文中将继续分享另外一款优秀的垃圾回收器 Shenandoah, 不过 Shenandoah 目前只能在 openjdk12 中使用。

2 Shenandoah 垃圾回收器

Shenandoah 垃圾回收器不是 Oracle 开发的垃圾回收器,而是由 RetHat 独立开发的,Shenandoah 和 G1 有这相似的内存布局,在初始标记、并发标记阶段有着共同的操作,Shenandoah 没有使用分代收集的概念,它摒弃了在 G1 中耗费大量内存和计算资源去维护的记忆集,而是采用邻接矩阵来记录全局数据结构,并记录跨 Region 的引用关系,这样的做法降低了维护记忆集的维护消耗,页降低了伪共享发生的概率。关于连接矩阵的示意图如下图所示:

利用邻接矩阵这样的结构,比记忆集这样的结构更节省空间。

3 垃圾回收过程

Shenandoah 垃圾回收的步骤就比较复杂了,可以分为并发标记、并发回收和并发引用更新三大步骤,标记阶段有初始标记、并发标记、最终标记、并发清理、并发回收等过程,关于引用更新,可以分为初始引用更新、并发引用更新、最终引用更新和并发清理等过程。

关于标记和回收都是熟悉的概念,但是引用更新是一个新的概念,引用更新即并发回收复制结束后,需要把堆中的所有指向旧对象的引用修正到复制后的新地址,这个操作称之为引用更新。 经历过并发回收和引用更新之后,整个回收集中所有的 Region 已经没有存活的对象,这些 Region 都会变成 不可变的对象区域,最后再调用一次并发清理过程来回收这些 Region 的内存空间,供以后新对象分配使用。

4 转发指针

Shenandoah 引入了一个转发指针的概念,用来实现对象移动与用户线程之间的并发操作。

在使用转发指针解决此问题之前,想要做并发的操作,通常需要在被转义对象的内存上设置内存保护陷阱,当用户线程访问到归属于旧对象的内存空间便会产生中断子线,进入预设好的异常处理器中,再由其中的代码逻辑将访问转发到复制后的新对象上。但是这种操作代价比较大,不能频繁使用。

5 总结

在本文中,讲述了高效的 Shenandoah 垃圾回收器,至此,G1 、ZGC、Shenandoah 等三款垃圾回收器已经全部讲解完毕,希望有助于学习 jvm 有关的知识。