深入理解JVM(③)低延迟的Shenandoah收集器
前言
Shenandoah作为第一款不由Oracle(包括一起的Sun)公司的虚拟机团队所领导开发的HotSpot垃圾收集器。是只存在于OpenJDK当中的,最初由RedHat公司创建的,在2014年的时候贡献给了OpenJDK。
与G1相比的优点
从代码的历史渊源上来看,Shenandoah收集器更像是G1的下一代继承者,两者相似的堆内存布局,在初始标记、并发标记等许多阶段的处理思路都高度一致。
但是Shenandoah相比G1还是至少有三个明显的不同之处。
1、支持并发的整理算法,G1的回收阶段是可以多线程并行的,但却不鞥呢与用户线程并发。
2、Shenandoah是默认不使用分代收集的,不会有专门的新生代Region或者老年代Region的存在。
3、Shenandoah摒弃了在G1中耗费大量内存和计算资源去维护的记忆集,改用名为“连接矩阵”(Connection Matrix)的全局数据结果来记录夸Region的引用关系降低了夸代维护的消耗。
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 转发指针在设计上决定了它是必然会出现多线程竞争问题的。Shenandoah收集器是通过比较交换(Compare And Swap,CAS)操作来保证并发时堆中的访问正确性的。
总结
1、Shenandoah收集器保证了收集垃圾的低延迟。
2、但是使用了过多的写屏障,所以导致Shenandoah收集器的弱项很明显,当数据量大的时候会产生高运行负担而使得吞吐量下降。
深入理解JVM(③)低延迟的Shenandoah收集器的更多相关文章
- JVM 低延迟垃圾收集器 Shenandoah 和 ZGC
本文部分摘自<深入理解 Java 虚拟机第三版> 概述 衡量垃圾收集器的三项指标分别是:内存占用.吞吐量和延迟.这三者共同构成一个"不可能三角",即一款优秀的收集器最多 ...
- [深入理解JVM虚拟机]第3章-垃圾收集器、内存分配策略
垃圾收集器 判断对象是否需存活 回收堆 判断对象是否存活: 方法一:引用计数法.对象被引用一次就+1,当为0时回收对象.缺点:无法解决循环引用问题. 方法二:可达性分析算法.记录当前对象是否有和GC ...
- 深入理解java虚拟机笔记Chapter3-垃圾收集器
垃圾收集器 垃圾收集(Garbage Collection,GC),它的任务是解决以下 3 件问题: 哪些内存需要回收? 什么时候回收? 如何回收? 本节补充知识: ① s:Survivor区 新生代 ...
- JVM学习记录3--垃圾收集器
贴个图 Serial收集器 最简单的收集器,单线程,收集器会暂停用户线程,称为"stop the world". ParNew收集器 Serial收集器的多线程版本,其它类似.默认 ...
- JVM垃圾回收之CMS收集器
从前文JVM垃圾回收几种常见算法和常见收集器我们知道,CMS是老年代垃圾收集器.CMS 收集器主要关注系统停顿时间.CMS 是 Concurrent Mark Sweep 的缩写,意为并发标记清除,从 ...
- 深入理解JVM(5)——HotSpot垃圾收集器详解
HotSpot虚拟机提供了多种垃圾收集器,每种收集器都有各自的特点,没有最好的垃圾收集器,只有最适合的垃圾收集器.根据新生代和老年代各自的特点,我们应该分别为它们选择不同的收集器,以提升垃圾回收效率. ...
- 深入理解JVM(③)虚拟机的类加载器(双亲委派模型)
前言 先解释一下什么是类加载器,通过一个类的全限定名来获取描述该类的二进制字节流,在虚拟机中实现这个动作的代码被称为"类加载器(Class Loader)". 类与类加载器 类加载 ...
- JVM实用参数(七)CMS收集器
HotSpot JVM的并发标记清理收集器(CMS收集器)的主要目标就是:低应用停顿时间.该目标对于大多数交互式应用很重要,比如web应用.在我们看一下有关JVM的参数之前,让我们简要回顾CMS收集器 ...
- JVM笔记-垃圾收集算法与垃圾收集器
1. 一些概念 1.1 垃圾&垃圾收集 垃圾:在 JVM 语境下,"垃圾"指的是死亡的对象所占据的堆空间. 垃圾收集:所谓"垃圾收集",就是将已分配出去 ...
随机推荐
- el-select检索功能
使用element-UI框架的使用,我们经常使用el-select下拉框,很多时候还需要使用可搜索的下拉框,然后elementUI官网的实例中只是提了一下filter-method可以自定义搜索方法, ...
- MySQL的CHAR 和 VARCHAR的区别
CHAR 和 VARCHAR 类型,CHAR 列的长度固定, VARCHAR 列中的值为可变长字符串.在检索的时候,CHAR 列删除了尾部的空格,而 VARCHAR 则保留这些空格s
- SpringBoot自定义装配的多种实现方法
Spring手动装配实现 对于需要加载的类文件,使用@Configuration/@Component/@Service/@Repository修饰 @Configuration public cla ...
- 从Student类和Teacher类多重派生Graduate类 代码参考
#include <iostream> #include <cstring> using namespace std; class Person { private: char ...
- nginx配置https及Android客户端访问自签名证书
前一篇随笔通过keytool生成keystore并为tomcat配置https,这篇随笔记录如何给nginx配置https.如果nginx已配置https,则tomcat就不需要再配置https了.通 ...
- ms-setting是什么
ms-settings 遇到了两个问题,记录一下 1)windows桌面右键菜单-->显示设置或者个性化-->报错:ms-settings:personalization-backgrou ...
- Bitwarden_rs搭建
最近LastPass网络极其不稳定,正好闲下来找到了Bitwarden_rs这个替代品,感觉不错,分享记录下部署过程. 一.Docker方式部署 #获取镜像 docker pull bitwarden ...
- 和付费网盘说再见,跟着本文自己起个网盘(Java 开源项目)
本文适合有 Java 基础知识的人群,跟着本文可学习和运行 Java 网盘项目. 本文作者:HelloGitHub-秦人 HelloGitHub 推出的<讲解开源项目>系列. 今天给大家带 ...
- Shell 脚本(五) Shell 工具 及 企业面试题
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 十.Shell工具(重点) 1.cut cut 的工作就是“剪”,具体的说就是在文件中负责剪切数据用的. ...
- Java实现 LeetCode 812 最大三角形面积 (暴力)
812. 最大三角形面积 给定包含多个点的集合,从其中取三个点组成三角形,返回能组成的最大三角形的面积. 示例: 输入: points = [[0,0],[0,1],[1,0],[0,2],[2,0] ...