如果下面的一些概念有些不清楚的可以先看深入理解JVM - 垃圾收集器和深入理解JVM - Shenandoah垃圾收集器。

ZGC(Z Garbage Collector)是一款由Oracle公司研发的,以低延迟为首要目标的一款垃圾收集器。它是基于动态Region内存布局,(暂时)不设年龄分代,使用了读屏障染色指针内存多重映射等技术来实现可并发的标记-整理算法的收集器。在JDK 11新加入,还在实验阶段,主要特点是:回收TB级内存(最大4T),停顿时间不超过10ms

动态Region

ZGC的Region可以具有如图所示的大、中、小三类容量:

  • 小型Region(Small Region):容量固定为2MB,用于放置小于256KB的小对象。
  • 中型Region(Medium Region):容量固定为32MB,用于放置大于等于256KB但小于4MB的对象。·
  • 大型Region(Large Region):容量不固定,可以动态变化,但必须为2MB的整数倍,用于放置4MB或以上的大对象。每个大型Region中只会存放一个大对象,最小容量可低至4MB,所有大型Region可能小于中型Region。大型Region在ZGC的实现中是不会被重分配的,因为复制一个大对象的代价非常高昂。

染色指针技术

HotSpot虚拟机的标记实现方案有如下几种:

  1. 把标记直接记录在对象头上(如Serial收集器);
  2. 把标记记录在与对象相互独立的数据结构上(如G1、Shenandoah使用了一种相当于堆内存的1/64大小的,称为BitMap的结构来记录标记信息);
  3. 直接把标记信息记在引用对象的指针上(如ZGC)

染色指针是一种直接将少量额外的信息存储在指针上的技术。目前在Linux下64位的操作系统中高18位是不能用来寻址的,但是剩余的46为却可以支持64T的空间,到目前为止我们几乎还用不到这么多内存。于是ZGC将46位中的高4位取出,用来存储4个标志位,剩余的42位可以支持4T的内存,如图所示:

  • Linux下64位指针的高18位不能用来寻址,所有不能使用;
  • Finalizable:表示是否只能通过finalize()方法才能被访问到,其他途径不行;
  • Remapped:表示是否进入了重分配集(即被移动过);
  • Marked1、Marked0:表示对象的三色标记状态;
  • 最后42用来存对象地址,最大支持4T;

三色标记

在并发的可达性分析算法中我们使用三色标记(Tri-color Marking)来标记对象是否被收集器访问过:

  • 白色:表示对象尚未被垃圾收集器访问过。显然在可达性分析刚刚开始的阶段,所有的对象都是白色的,若在分析结束的阶段,仍然是白色的对象,即代表不可达。
  • 黑色:表示对象已经被垃圾收集器访问过,且这个对象的所有引用都已经扫描过。黑色的对象代表已经扫描过,它是安全存活的,如果有其他对象引用指向了黑色对象,无须重新扫描一遍。黑色对象不可能直接(不经过灰色对象)指向某个白色对象
  • 灰色:表示对象已经被垃圾收集器访问过,但这个对象上至少存在一个引用还没有被扫描过。

可达性分析的扫描过程,其实就是一股以灰色为波峰的波纹从黑向白推进的过程,但是在并发的推进过程中会产生“对象消失”的问题,如图:、

对象消失理论,只有同时满足才会发生对象消失:

  • 赋值器插入了一条或多条从黑色对象到白色对象的新引用;
  • 赋值器删除了全部从灰色对象到该白色对象的直接或间接引用;

要解决对象消失问题只需要破坏其中一条就行了,目前常用有两种方案:

  • 增量更新(Incremental Update):增量更新要破坏的是第一个条件,当黑色对象插入新的指向白色对象的引用关系时,就将这个新插入的引用记录下来,等并发扫描结束之后,再将这些记录过的引用关系中的黑色对象为根,重新扫描一次。这可以简化理解为,黑色对象一旦新插入了指向白色对象的引用之后,它就变回灰色对象了。
  • 原始快照(Snapshot At TheBeginning,SATB):原始快照要破坏的是第二个条件,当灰色对象要删除指向白色对象的引用关系时,就将这个要删除的引用记录下来,在并发扫描结束之后,再将这些记录过的引用关系中的灰色对象为根,重新扫描一次。这也可以简化理解为,无论引用关系删除与否,都会按照刚刚开始扫描那一刻的对象图快照来进行搜索。

以上无论是对引用关系记录的插入还是删除,虚拟机的记录操作都是通过写屏障实现的。CMS是基于增量更新来做并发标记的,G1、Shenandoah则是用原始快照来实现。

染色指针的三大优势

  1. 一旦某个Region的存活对象被移走之后,这个Region立即就能够被释放和重用掉,而不必等待整个堆中所有指向该Region的引用都被修正后才能清理,这使得理论上只要还有一个空闲Region,ZGC就能完成收集。而Shenandoah需要等到更新阶段结束才能释放回收集中的Region,如果Region里面对象都存活的时候,需要1:1的空间才能完成收集。
  2. 染色指针可以大幅减少在垃圾收集过程中内存屏障的使用数量,ZGC只使用了读屏障。
  3. 染色指针具备强大的扩展性,它可以作为一种可扩展的存储结构用来记录更多与对象标记、重定位过程相关的数据,以便日后进一步提高性能。

内存多重映射

ZGC使用了内存多重映射(Multi-Mapping)将多个不同的虚拟内存地址映射到同一个物理内存地址上,这是一种多对一映射,意味着ZGC在虚拟内存中看到的地址空间要比实际的堆内存容量来得更大。把染色指针中的标志位看作是地址的分段符,那只要将这些不同的地址段都映射到同一个物理内存空间,经过多重映射转换后,就可以使用染色指针正常进行寻址了,效果如图:

ZGC的多重映射只是它采用染色指针技术的伴生产物

读屏障

当对象从堆中加载的时候,就会使用到读屏障(Load Barrier)。这里使用读屏障的主要作用就是检查指针上的三色标记位,根据标记位判断出对象是否被移动过,如果没有可以直接访问,如果移动过就需要进行“自愈”(对象访问会变慢,但也只会有一次变慢),当“自愈”完成后,后续访问就不会变慢了。

读写屏障可以理解成对象访问的“AOP”操作

ZGC运作过程

ZGC的运作过程大致可划分为以下四个大的阶段:

  • 并发标记(Concurrent Mark):与G1、Shenandoah一样,并发标记是遍历对象图做可达性分析的阶段,它的初始标记和最终标记也会出现短暂的停顿,整个标记阶段只会更新染色指针中的Marked 0、Marked 1标志位。
  • 并发预备重分配(Concurrent Prepare for Relocate):这个阶段需要根据特定的查询条件统计得出本次收集过程要清理哪些Region,将这些Region组成重分配集(Relocation Set)。ZGC每次回收都会扫描所有的Region,用范围更大的扫描成本换取省去G1中记忆集的维护成本。
  • 并发重分配(Concurrent Relocate):重分配是ZGC执行过程中的核心阶段,这个过程要把重分配集中的存活对象复制到新的Region上,并为重分配集中的每个Region维护一个转发表(Forward Table),记录从旧对象到新对象的转向关系。ZGC收集器能仅从引用上就明确得知一个对象是否处于重分配集之中,如果用户线程此时并发访问了位于重分配集中的对象,这次访问将会被预置的内存屏障所截获,然后立即根据Region上的转发表记录将访问转发到新复制的对象上,并同时修正更新该引用的值,使其直接指向新对象,ZGC将这种行为称为指针的“自愈”(Self-Healing)能力。

ZGC的染色指针因为“自愈”(Self-Healing)能力,所以只有第一次访问旧对象会变慢,而Shenandoah的Brooks转发指针是每次都会变慢。
一旦重分配集中某个Region的存活对象都复制完毕后,这个Region就可以立即释放用于新对象的分配,但是转发表还得留着不能释放掉,因为可能还有访问在使用这个转发表。

  • 并发重映射(Concurrent Remap):重映射所做的就是修正整个堆中指向重分配集中旧对象的所有引用,但是ZGC中对象引用存在“自愈”功能,所以这个重映射操作并不是很迫切。ZGC很巧妙地把并发重映射阶段要做的工作,合并到了下一次垃圾收集循环中的并发标记阶段里去完成,反正它们都是要遍历所有对象的,这样合并就节省了一次遍历对象图的开销。

ZGC存在的问题

ZGC最大的问题是浮动垃圾。

浮动垃圾

ZGC的停顿时间是在10ms以下,但是ZGC的执行时间还是远远大于这个时间的。假如ZGC全过程需要执行10分钟,在这个期间由于对象分配速率很高,将创建大量的新对象,这些对象很难进入当次GC,所以只能在下次GC的时候进行回收,这些只能等到下次GC才能回收的对象就是浮动垃圾

ZGC没有分代概念,每次都需要进行全堆扫描,导致一些“朝生夕死”的对象没能及时的被回收。

解决方案

目前唯一的办法是增大堆的容量,使得程序得到更多的喘息时间,但是这个也是一个治标不治本的方案。如果需要从根本上解决这个问题,还是需要引入分代收集,让新生对象都在一个专门的区域中创建,然后专门针对这个区域进行更频繁、更快的收集。

官方测试数据

停顿时间

在ZGC的停顿时间测试上,和其他收集器相比完全不在一个数量级,如图:

吞吐量

ZGC的“弱项”吞吐量方面,以低延迟为首要目标的ZGC已经达到了以高吞吐量为目标Parallel Scavenge的99%,直接超越了G1,如图:

优缺点

  • 优点:低停顿,高吞吐量,ZGC收集过程中额外耗费的内存小
  • 缺点:浮动垃圾

参考

《深入理解JAVA虚拟机》

深入理解JVM - ZGC垃圾收集器相关推荐

  1. 深入理解JVM - Shenandoah垃圾收集器

    如果下面的一些概念有些不清楚的可以先看深入理解JVM - 垃圾收集器. Shenandoah是一款只有OpenJDK才会包含的收集器,最开始由RedHat公司独立发展后来贡献给了OpenJDK,相比G ...

  2. JVM垃圾回收——ZGC垃圾收集器

    目录 一.什么是ZGC垃圾收集器 二.ZGC的内存模型 三.收集过程 染色指针 多重映射 收集过程 四.优缺点 五.参数配置 一.什么是ZGC垃圾收集器 ZGC(Z Garbage Collector ...

  3. JVM常用垃圾收集器

    前言 在上一篇,我们谈到了JVM中的常用垃圾回收算法,并了解了JVM中针对堆区中不同的分代采用不同的垃圾回收算法 在了解了垃圾回收算法之后,很多伙伴不禁在想,既然是分代垃圾回收,自然新生代和老年代的垃 ...

  4. JVM之垃圾收集器回收种类

    JVM之垃圾收集器回收种类 目录 面试常见问题 串行并行并发G1四大垃圾回收方式 如何查看默认的垃圾收集器 JVM默认的垃圾收集器有哪些 GC之7大垃圾收集器详解 1. 面试常见问题 GC垃圾回收算法 ...

  5. JVM(四)--垃圾收集器

    JVM(四)–垃圾收集器 这篇博客的内容包括: 一.垃圾收集器: 1,Serial 收集器: 2,ParNew 收集器: 3, Parallel Scavenge 收集器: 4,Serial Old收 ...

  6. G1和ZGC垃圾收集器

    文章目录 G1垃圾收集器 定义 G1的优势 G1架构 G1 内存布局 G1可以让用户自己设置应用暂停时间,为什么可以做到这一点? G1 缺点 G1 GC模式 G1 Young GC Mixed GC ...

  7. java垃圾收集器zgc_java虚拟机ZGC垃圾收集器的实现方法

    java虚拟机垃圾回收算法和工具是我们在学习java虚拟机的时候需要重点掌握的编程知识,而今天我们就通过案例分析来了解一下,java虚拟机ZGC垃圾收集器的实现方法. 1.染色指针 HotSpot的垃 ...

  8. java -g_【JVM】7、深入理解Java G1垃圾收集器

    本文首先简单介绍了垃圾收集的常见方式,然后再分析了G1收集器的收集原理,相比其他垃圾收集器的优势,最后给出了一些调优实践. 一,什么是垃圾回收 首先,在了解G1之前,我们需要清楚的知道,垃圾回收是什么 ...

  9. 详解ZGC垃圾收集器

    从G1垃圾收集器开始,后面的垃圾收集器都不再将堆按照新生代和老年代作为整体进行回收,都采用了局部收集的设计思想. 可能是由于G1作为第一代局部收集的垃圾收集器,所以它继续保留了新生代和老年代的概念,笔 ...

最新文章

  1. iOS自动化测试之Appium的安装和使用
  2. Windows 11 正式官宣:全新 UI、支持安卓 App、应用商店 0 抽成!
  3. [总结]Asp.net中的页面乱码的问题
  4. struc,union,class的内存对齐方式
  5. [转载].一直不怎么明白PID的运算输出结果怎么换算成执行机构的控制量
  6. 2019杭电多校第九场 Rikka with Cake (hdu6681)
  7. 【Java从0到架构师】交错的日志系统、SpringBoot 集成日志框架
  8. 网页自动切换html css js,HTML页面自动清理js、css文件的缓存(自动添加版本号)_HTML/Xhtml_网页制作...
  9. cve-2018-2893 WebLogic
  10. 唐宇迪ocr检测图片
  11. Word VBA查找表格单元格的第一段
  12. 怎么把pdf文件压缩到最小?
  13. python图中图_【python】matplotlib数据可视化(7)——图中图
  14. 元旦用SpringBoot撸了个博客网站送给大家
  15. CTF实验吧-简单的sql注入【SQL注入关键词绕过】
  16. 简单的例子理解正则表达式中的前瞻与后顾
  17. python人文社科研究_人文社科论文写作数据分析利器|SPSS+Stata+Endnote+Python
  18. QT With OpenGL(泛光)(Bloom)
  19. 5G网络与5G WiFi有什么区别
  20. c++游戏编程三国杀

热门文章

  1. 第十五期】Monica:单身滴美女程序员 多图!
  2. VTP-------详解
  3. 7-3 电话聊天狂人 (25 分)
  4. 中国市场超阿迪耐克 安踏领衔打响国货反击战
  5. CSS的再深入2(更新中···)
  6. 面试经历-201106
  7. HBase数据大批量导入方式总结和对比
  8. 实例化对象是什么意思,什么是实例化,什么是对象。多态性
  9. 使用C++和Boost库写一个自己的脚本引擎
  10. 2006年6月26日之足球不眠夜---意大利+黄健翔VS澳大利亚