简介

  • Shenandoah GC 与 ZGC 同为新一代的低延迟收集器, 分别由RedHat和Oracle开发, 目前还在实验阶段, 尚未使用于生产环境。

  • GC的三项指标: Footprint(内存占用), Throughput(吞吐量) 与 Latency(延迟), 有点像CAP理论, 三者只能取其二。

  • 目前主流GC是G1, 而此两者的延时比G1低很多。

Shenandoah GC

  • 操作系统支持:

    • Linux, Windows, macOS, Solaris
  • 硬件支持:

    • x86_64

    • x86_32

    • AArch64

  • JDK支持(注意是OpenJDK的非Oracle Build, 因为Oracle不想为RedHat写的代码负责任)

    • JDK8, JDK11, JDK13
  • Shenandoah 与 G1

    • Shenandoah 可以说是G1的下一代继承者

      • 它们拥有相似的堆内存布局
      • 在初始标记, 并发标记等多阶段的处理思路上都高度一致, 甚至共享了一部分实现代码
    • Shenandoah 相比 G1的改进:

      • 堆内存管理方面:

        • 支持并发的整理算法, 能与用户线程并发

        • 默认不使用分代收集

        • 摒弃了在G1中耗费大量内存和计算资源去维护的记忆集(Memory Set), 改用名为连接矩阵(Connection Matrix) 的全局数据结构来记录跨Region的引用关系。从而降低了处理跨带指针时的记忆集维护消耗以及伪共享问题的发生概率。

          • 连接矩阵示意图(其实这张图好像错了, 第一行的X应该在[3, 1]的位置)

            • 说白了这就是个临接矩阵, 横坐标代表当前区域, 纵坐标代表当前区域引用的区域
            • 那么就是区域5引用了区域3, 而区域3又引用了区域1
  • Shenandoah GC的工作过程大致可划分为9个阶段

    • Initial Marking(初始标记)

      • 与G1一致, 首先标记与GC Roots直接关联的对象, 此阶段仍会"Stop The World", 但停顿时间与堆大小无关, 只与GC Roots的数量相关。
    • Concurrent Marking(并发标记)

      • 与G1一致, 遍历对象图, 标记出全部可达的对象, 此阶段是与用户线程一起并发的, 时间长短取决于堆中存活对象的数量以及图的结构复杂程度。
    • Final Marking(最终标记)

      • 与G1一致, 处理剩余的SATB扫描, 并在此阶段统计出回收价值最高的Region, 将这些Region构成一组回收集(Collection Set)。

      • 最终标记阶段也会有一小段短暂的停顿。

    • Concurrent Cleanup(并发清理)

      • 此阶段用于清理那些整个区域内连一个存活对象都没有找到的Region(Immediate Garbage Region)
    • Concurrent Evacuation(并发回收)

      • 在此阶段, Shenandoah要把回收集里面的存活对象先复制一份到其他未被使用的Region中。

      • 重点是复制对象过程不冻结用户线程而是与用户线程并行, 这一实现有很大的技术屏障, Shenandoah 通过读屏障和 Brooks Pointers(转发指针) 解决了此困难。

      • 并发回收阶段运行时间长短取决于回收集的大小。

    • Initial Update Reference(初始引用更新)

      • 并发回首阶段复制对象结束后, 还需要把堆中所有指向旧对象的引用修正到复制后的新地址, 此操作称为引用更新。

      • 实际上此阶段并没有做什么实际的处理, 只是为了建立一个线程集合点, 确保所有并发回收阶段中进行的收集器线程都已完成分配给它们的对象移动任务而已。

      • 初始引用更新时间很短, 会产生一个非常短暂的停顿。

    • Concurrent Update Reference(并发引用更新)

      • 真正开始引用更新操作, 此阶段是与用户线程并发的, 时间长短取决于内存中涉及的引用数量的多少。

      • 与并发标记不同, 不需要再沿着对象图来搜索, 只需要按照内存物理地址的顺序, 线性地搜索出引用类型, 把旧值改为新值即可。

    • Final Update Reference(最终引用更新)

      • 处理了堆中的引用更新后, 还需要修正存于GC Roots中的引用。

      • 此阶段是Shenandoah的最后一次停顿, 停顿事件只与GC Roots数量相关。

    • Concurrent Cleanup(并发清理)

      • 经过并发回收和引用更新之后, 整个回收集中所有的Region已再无存活对象, 这些Region都变成了Immediate Garbage Regions了。

      • 最后再调用一次并发清理过程来回收这些Region的内存空间, 供以后新对象分配使用。

  • 工作过程示意图

    • 白色: 自由空间

    • 蓝色: 新分配的空间

    • 绿色: 存活的对象

    • 黄绿白: 被选入回收集的存活对象

    • 黄黄白: 需要更新引用的被选入回收集的存活对象

ZGC

  • 可以说是Oracle抄了 Azul System的作业, ZGC 与 Azul System公司的PGC(Pauseless GC) 和 C4(Concurrent Continuously Compacting Collector) 在算法和实现原理上是高度相似的, 只存在术语称谓的区别。

  • 主要特征:

    • 基于Region内存布局
    • 不设分代
    • 使用了读屏障, 染色指针和内存多重映射等技术来实现可并发的标记-整理算法
    • 以低延迟为首要目标
  • ZGC也采用基于Region的堆内存布局, 但与它们不同的是, ZGC的Region具有动态性: 动态创建和销毁, 以及动态的区域容量大小。在x64硬件平台下, ZGC的Region可以有以下三类容量:

    • Small Region

      • 容量固定为2MB, 用于放置小于256KB的小对象。
    • Medium Region

      • 容量固定为32MB, 用于放置大于等于256KB但小于4MB的对象。
    • Large Region

      • 容量不固定, 可以动态变化, 但必须为2MB的整数倍, 用于放置4MB或以上的大对象。
      • 每个大型Region中只会存放一个大对象, 它虽名为Large Region, 但它的实际容量完全有可能小于中型Region。
      • 大型Region在ZGC的实现中是不会被重分配的, 因为复制一个大对象的代价非常高昂。
  • 染色指针技术

    • 在64位系统中, 理论可以访问的内存高达16EB。实际上基于需求, 性能, 和成本考虑, 在AMD64架构中只支持到52位(4PB)的地址总线和48位(256TB)的虚拟地址空间, 目前64位的硬件实际能够支持的最大内存只有256TB。此外操作系统还有自己的约束, 64Linux系统分别支持47位(128TB)的进程虚拟地址和46位(64TB)的物理地址空间, 64位的Windows系统只支持44位(16TB)的物理地址空间。

    • 虽然Linux下64位指针的高18位不能用来寻址, 剩余的46位指针所能支持的64TB内存在今天仍能够充分满足大型服务器需要。而ZGC则利用了剩下的46位指针的高4位提取出来用于存储四个标志信息。

      • 通过这些标志位, 虚拟机可以直接从指针中看到其引用对象的状态, 是否进入重分配集, 是否通过finalize()方法才能被访问到。
      • 由于进一步压缩了原本只有46位的地址空间, ZGC能够管理的内存不可以超过4TB。
    • 三大优势

      • 染色指针可以使得一旦某个Region的存活对象被移走之后, 此Region立即就能够被释放和重用掉, 而不必等待整个堆中所有指向该Region的引用都被修正后才能清理。
      • 染色指针可以大幅减少在垃圾收集过程中内存屏障的使用数量。
      • 染色指针可以作为一种可扩展的存储结构用来记录更多与对象标记、重定位过程相关的数据, 以便日后进一步提高性能。
    • 在Linux/X86-64平台上的ZGC使用了多重映射(Multi-Mapping) 将多个不同的虚拟内存映射到同一个物理内存地址上。

      • 任何的进程在进程自己看来自己的内存空间都是连续的, 但是计算机实际的物理内存并不是与该进程的内存是一一对应的。碎片化的物理内存可以映射成一个完整的虚拟内存, 同时应用可以申请比物理内存大的内存, 使得多个内存互不干扰, 使编译好的二进制文件的地址统一化......
    • ZGC运作过程

      • Concurrent Mark(并发标记)

        • 遍历对象图做可达性分析的阶段, 前后也要经过类似于G1, Shenandoah 的初始标记, 最终标记的短暂停顿。

        • 与G1, Shenandoah不同的是, ZGC的标记是在指针上而不是在对象上进行的, 标记阶段会更新染色指针中的Marked0、Marked1标志位。

      • Concurrent Prepare for Relocate(并发预备重分配)

        • 此阶段需要根据特定的查询条件统计出本次收集过程要清理哪些Region, 将这些Region组成重分配集(Relocation Set)。
      • Concurrent Relocate(并发重分配)

        • 是ZGC执行过程中的核心阶段, 此过程要把重分配集中的存活对象复制到新的Region上, 并为重分配集中的每个Region维护一个转发表(Forward Table), 记录从旧对象到新对象的转向关系。

        • 由于染色指针的存在, ZGC能仅从引用上就明确得知一个对象是否处于重分配集之中。如果用户线程此时并发访问了位于重分配集中的对象, 这次访问将会被预置的内存屏障截获, 然后立即根据Region上的转发表记录将访问转发到新复制的对象上, 并同时修正该引用的值, 使其直接指向新对象, 此即为Self-Healing(自愈)[只有第一次访问旧对象会陷入转发]。

      • Concurrent Remap(并发重映射)

        • 修正整个堆中指向重分配集中旧对象的所有引用。
        • 重映射清理这些旧引用的主要目的是为了不变慢, 并不是很迫切。
        • ZGC将并发重映射阶段要做的工作, 合并到了下一次垃圾收集循环中的并发标记阶段里去完成, 从而节省了一次遍历对象图的开销。

Shenandoah 与 ZGC的更多相关文章

  1. JVM 低延迟垃圾收集器 Shenandoah 和 ZGC

    本文部分摘自<深入理解 Java 虚拟机第三版> 概述 衡量垃圾收集器的三项指标分别是:内存占用.吞吐量和延迟.这三者共同构成一个"不可能三角",即一款优秀的收集器最多 ...

  2. JDK15正式发布,划时代的ZGC同时宣布转正

    你发任你发,我用Java8.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众号[BA ...

  3. Java 9和Java 10的新特性

    http://www.infoq.com/cn/news/2014/09/java9 Java 9新特性汇总 继2014年3月份Java 8发布之后,Open JDK加快了开发速度, Java 9的发 ...

  4. JDK 15 JAVA 15的新特性展望

    目录 JEP 371: Hidden Classes JEP 372: 删除 Nashorn JavaScript Engine JEP 377: 新的垃圾回收器ZGC正式上线了 JEP 378: T ...

  5. JVM垃圾回收(五)

    低延迟垃圾收集器 衡量垃圾收集器的三项最重要的指标是: 内存占用(Footprint).吞吐量(Throughput)和延迟(Latency).三者总体的表现会随技术进步而越来越好,但是要在这三个方面 ...

  6. 深入探究JVM之垃圾回收算法实现细节

    @ 目录 前言 垃圾回收算法实现细节 根节点枚举 安全点 安全区域 记忆集和卡表 写屏障 并发的可达性分析 低延迟GC Shenandoah ZGC 总结 前言 本篇紧接上文,主要讲解垃圾回收算法的实 ...

  7. 技术基础 | Apache Cassandra 4.0基准测试

    Apache Cassandra 4.0已经发布了Beta版,这是第一个支持JDK 11及更高JDK版本的Cassandra版本.   时延对于Apache Cassandra用户来说是个显而易见的关 ...

  8. JVM经典垃圾收集器

      这个关系不是一成不变的,由于维护和兼容性测试的成本,在JDK 8时将Serial+CMS. ParNew+Serial Old这两个组合声明为废弃(JEP 173),并在JDK 9中完全取消了这些 ...

  9. 《深入理解java虚拟机》第3版笔记3

    第3章 垃圾收集器与内存分配策略 可达性分析算法 在Java技术体系里面,固定可作为GC Roots的对象包括以下几种: 在虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法堆栈中使 ...

随机推荐

  1. vue axios路由跳转取消所有请求 和 防止重复请求

    直接上干货 在发送第二次请求的时候如果第一次请求还未返回,则取消第一次请求,以保证后发送的请求返回的数据不会被先发送的请求覆盖. 或者是跳转路由的时候取消还未返回的请求 第一步: axios 怎么取消 ...

  2. Draw.io--自认为最好用的流程图绘制软件

    draw.io 是一个强大简洁的在线的绘图网站,支持流程图,UML图,架构图,原型图等图标.支持Github,Google Drive, One drive等网盘同步,并且永久免费.如果觉得使用Web ...

  3. C语言:将s所指字符串中下标为偶数同时ASCII值为奇数的字符删去,-将a所指字符串中的字符和b所指字符串中的字符的顺序交叉,-将形参s所指字符串中的所有数字字符顺序前移,

    //函数fun功能:将s所指字符串中下标为偶数同时ASCII值为奇数的字符删去,s所指串中剩余的字符形成的新串放在t所指的数组中. #include <stdio.h> #include ...

  4. 计算机二级-C语言-程序设计题-190118记录-通过数组和指针两种方式对字符串进行处理。

    //编写一个函数fun,比较两个字符串的长度,(不使用C语言提供的求字符串长度的函数),函数返回较长的字符串.若两个字符长度相同,则返回第一个字符串. //重难点:通过数组处理和通过指针进行处理的不同 ...

  5. C++基础之迭代器iterator

    C++基础之迭代器iterator 我们已经知道可以使用下标运算符来访问string对象的字符或vector对象的元素,还有另一种更通用的机制也可以实现同样的目的,这就是迭代器(iterator). ...

  6. 《JavaScript高级程序设计》读书笔记(三)基本概念第三小节 String、Object类型

    内容---语法 上一小节---数据类型 本小节 String类型---流程控制语句---理解函数 String类型--零个或者多个16位Unicode字符组成字符序列,即字符串--可以由双引号&quo ...

  7. DL4J之CNN对今日头条文本分类

    一.数据集介绍 数据来源:今日头条客户端 数据格式如下: 6551700932705387022_!_101_!_news_culture_!_京城最值得你来场文化之旅的博物馆_!_保利集团,马未都, ...

  8. [BUUCTF 2018]Online Tool

    进入页面 贴出源码 <?php if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $_SERVER['REMOTE_ADDR'] = $_SERVER ...

  9. JQuery DOM操作:设置内容&属性&添加元素&插入元素&包裹&克隆&移除&替换

    JQuery text().html().val() $(elem).text(str):添加文本内容str到elem类型元素,返回jQuery对象 $(elem).text():返回第一个elem标 ...

  10. 吴裕雄--天生自然Numpy库学习笔记:NumPy 数据类型

    下表列举了常用 NumPy 基本类型. 名称 描述 bool_ 布尔型数据类型(True 或者 False) int_ 默认的整数类型(类似于 C 语言中的 long,int32 或 int64) i ...