深刻理解JVM(③)低延迟的Shenandoah收集器

前言

Shenandoah做为第一款不禁Oracle(包括一块儿的Sun)公司的虚拟机团队所领导开发的HotSpot垃圾收集器。是只存在于OpenJDK当中的,最初由RedHat公司建立的,在2014年的时候贡献给了OpenJDK。算法

与G1相比的优势

从代码的历史渊源上来看,Shenandoah收集器更像是G1的下一代继承者,二者类似的堆内存布局,在初始标记、并发标记等许多阶段的处理思路都高度一致。
可是Shenandoah相比G1仍是至少有三个明显的不一样之处。
一、支持并发的整理算法,G1的回收阶段是能够多线程并行的,但却不鞥呢与用户线程并发。
二、Shenandoah是默认不使用分代收集的,不会有专门的新生代Region或者老年代Region的存在。
三、Shenandoah摒弃了在G1中耗费大量内存和计算资源去维护的记忆集,改用名为“链接矩阵”(Connection Matrix)的全局数据结果来记录夸Region的引用关系下降了夸代维护的消耗。
Shenandoah收集器的跨代“链接矩阵”示意图
Shenandoah收集器链接矩阵
链接矩阵能够简单的理解为一张二维表格,若是Region N有对象指向Region M,就在表格的N行M列中打上一个标记,如上图所示,若是Region 5中的对象Object C引用了Region 3 的Object B,Object B又引用了Region 1 的Object A,那么链接矩阵就中就会在5行3列、3行1列中打上标记。在回收时经过这张表格就能够得出哪些Region 之间产生了跨代引用。多线程

收集过程

Shenandoah收集器的工做过程大体能够划分为如下九个阶段:并发

  • 初始标记:与G1同样,首先标记与GC Roots直接关联的对象,这个阶段还是“Stop The World”的,但停顿时间与堆大小无关,至于GC Roots的数量相关。
  • 并发标记:与G1同样,编辑对象图,标记出所有可达的对象,与用户线程一块儿并发,时间长短与堆中存活对象的数量以及对象图的结构复杂程度有关。
  • 最终标记:与G1同样,处理剩余的SATB扫描,并在这个阶段统计出回收价值最高的Region,将这些Region构成一组回收集。此阶段也会有一小段短暂的停顿。
  • 并发清理:这个阶段用于清理那些整个区域内连一个存活对象都没有找到的Region。
  • 并发回收:这个阶段是Shenandoah与以前HotSpot中其余收集器的核心差别。在这个阶段,Shenandoah要把回收集里面的存活对象先复制一份到其余未被使用的Region中。可是有个难点是在移动对象的同时,用户线程仍然可能不停的对被移动的对象进行读写访问,移动对象以后整个内存中全部指向该对象的引用都仍是旧对象的地址,这是很难一瞬间所有改变过来的。对于这个难点,Shenandoah将会经过读屏障和被称为“Brooks Pointers”的转发指针来解决
    并发回收阶段运行时间的长短取决于回收集的大小。
  • 初始引用更新:并发回收阶段复制对象结束后,还须要把堆中全部指向旧对象的引用修正蛋糕复制后的新地址,这个操做称为引用更新。这个阶段就是对这个操做进行初始化的,初始引用更新时间很短,会产生一个很是短暂的停顿。
  • 并发引用更新:真正开始进行引用更新操做,这个阶段是与用户线程一块儿并发的,时间长短取决于内存中涉及的引用数量的多少。
  • 最终引用更新:解决了堆中的引用更新后,还要修正存在于GC Roots 中的引用。这个阶段是Shenandoah的最后一次停顿,时间长短与GC Roots的数量有关。
  • 并发清理:通过并发回收和引用更新以后,整个回收集中全部的Region已再无存活对象,最后再调用一次并发清理过程来回收这些Region 的内存空间,供之后新对象分配使用。

这九个阶段的工做过程可能拆的比较琐碎,只要抓住其中三个最重要的并发节点(并发标记、并发回收、并发引用更新)就好理解Shenandoah的运做过程了。布局


转发指针(Brooks Pointer)

Shenandoah收集器的并发回收的核心是,转发指针。
转发指针的核心内容就是,在原有对象布局结构的最前面统一增长一个新的引用字段,在正常不处于并发移动的状况下,该引用指向对象本身。
以下图:
在这里插入图片描述
转发指针加入后带来的收益天然是当对象拥有了一份新的副本时,只须要修改一处指针的值,即旧对象上转发指针的引用位置,使其指向新对象,即可将全部对该对象的访问转发到新的副本上。这样只要对象的内存仍然存在,未被清理掉,虚拟机内存中全部经过旧引用地址访问的代码仍然可用,都会被自动转发到新对象上继续工做。
以下图:
Brooks Pointers
Brooks Pointers 转发指针在设计上决定了它是必然会出现多线程竞争问题的。Shenandoah收集器是经过比较交换(Compare And Swap,CAS)操做来保证并发时堆中的访问正确性的。线程

总结

一、Shenandoah收集器保证了收集垃圾的低延迟。
二、可是使用了过多的写屏障,因此致使Shenandoah收集器的弱项很明显,当数据量大的时候会产生高运行负担而使得吞吐量降低。设计

相关文章
相关标签/搜索