元月's blog 元月's blog
首页
  • 基础
  • 并发编程
  • JVM
  • Spring
  • Redis篇
  • Nginx篇
  • Kafka篇
  • Otter篇
  • Shardingsphere篇
  • 设计模式
  • MySQL
  • Oracle
  • 基础
  • 操作系统
  • 网络
  • 数据结构
  • 技术文档
  • Git常用命令
  • GitHub技巧
  • 博客搭建
  • 开发工具
更多

元月

临渊羡鱼,不如退而结网
首页
  • 基础
  • 并发编程
  • JVM
  • Spring
  • Redis篇
  • Nginx篇
  • Kafka篇
  • Otter篇
  • Shardingsphere篇
  • 设计模式
  • MySQL
  • Oracle
  • 基础
  • 操作系统
  • 网络
  • 数据结构
  • 技术文档
  • Git常用命令
  • GitHub技巧
  • 博客搭建
  • 开发工具
更多
  • 基础

  • 并发编程

  • JVM

    • Java的调试体系-JPDA架构
    • JVM整体结构和内存模型
    • 深度剖析JVM类加载机制
    • JVM对象创建与内存分配机制
    • JVM垃圾回收算法
    • JVM垃圾收集器一:Serial和Parallel收集器
    • JVM垃圾收集器二:CMS与三色标记算法详解
    • JVM垃圾收集器三:G1(Garbage First)
    • JVM垃圾收集器四:ZGC与颜色指针详解
      • 一、简介
      • 二、垃圾回收过程
        • 并发标记(Concurrent Mark)
        • 并发预备重分配(Concurrent Prepare for Relocate)
        • 并发重分配(Concurrent Relocate)
        • 并发重映射(Concurrent Remap)
      • 三、颜色指针
    • JVM调优之常用的调优指令
    • JVM调优之常用的调优工具
    • Arthas:一款优秀的Java诊断工具
    • 亿级流量系统JVM实战
  • Java基础
  • JVM
元月
2022-09-12
目录

JVM垃圾收集器四:ZGC与颜色指针详解

# JVM垃圾收集器四:ZGC与颜色指针详解

# 一、简介

ZGC是一款基于Region内存布局的, 暂时不设分代的, 使用了读屏障、 颜色指针等技术来实现可并发的标记-整理算法的, 以低延迟为首要目标的垃圾收集器。

ZGC是一款JDK 11中新加入的具有实验性质的低延迟垃圾收集器,ZGC可以说源自于是Azul System公司开发的C4(Concurrent Continuously Compacting Collector) 收集器。

ZGC的Region可以分为三种:小型Region、 中型Region、 大型Region:

  • 小型Region(Small Region) : 容量固定为2MB, 用于放置小于256KB的对象。

  • 中型Region(Medium Region) : 容量固定为32MB, 用于放置大于等于256KB但小于4MB的对象。

  • 大型Region(Large Region) : 容量不固定, 可以动态变化, 但必须为2MB的整数倍, 用于放置4MB及以上的大对象。 每个大型Region中只会存放一个大对象,

    这也预示着虽然名字叫作“大型Region”, 但它的实际容量完全有可能小于中型Region, 最小容量可低至4MB。

    大型Region是不会被重分配的(重分配是ZGC的一种处理动作, 用于复制对象的收集器阶段, 稍后会介绍到), 因为复制一个大对象的代价非常高昂。

# 二、垃圾回收过程

ZGC的收集过程主要分为四个阶段:

  • # 并发标记(Concurrent Mark)

    和G1相同的是,并发标记是遍历对象图做可达性分析的阶段,它的初始标记(Mark Start)和最终标记(Mark End)也会出现短暂的停顿。

    和G1不同的是, ZGC的标记是在指针上而不是在对象头上进行的, 并发标记阶段会更新颜色指针(见下面详解)中的Marked 0、 Marked 1标志位。

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

    这个阶段需要根据特定的查询条件统计出本次收集过程要清理哪些Region,将这些Region组成重分配集(Relocation Set)。ZGC每次回收都会扫描所有的Region,用范围更大的扫描成本换取省去G1中记忆集的维护成本。

  • # 并发重分配(Concurrent Relocate)

    这个阶段需要把重分配集中的存活对象复制到新的Region中,并且为重分配集中的每个Region维护了一个转发表(Forward Table),记录从旧对象到新对象的转向关系。

    ZGC仅从引用上就能明确得知一个对象是否处于重分配集之中,如果此时用户线程并发访问了位于重分配集中的对象,那么这次访问将会被读屏障所截获,然后立即根据Region上的转发表记录将访问转发到新复制的对象上,并同时修正更新该引用的值,使其直接指向新对象,ZGC将这种行为称为指针的“自愈”(Self-Healing)能力。

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

  • # 并发重映射(Concurrent Remap)

    重映射是为了修正整个堆中指向重分配集中旧对象的所有引用,但是ZGC中的对象引用存在“自愈”功能,所以这个重映射操作并不是很迫切。

    ZGC很巧妙地把这一阶段要做的工作,合并到了下一次的并发标记阶段,反正它们都是要遍历所有对象的,这样也就减少了一次遍历对象图的开销。一旦所有指针都被修正之后, 那么Region中的转发表就可以释放掉了。

# 三、颜色指针

颜色指针(Colored Pointers),是ZGC的核心设计之一。以前的垃圾回收器将GC信息保存在对象头中,而ZGC将GC信息保存在指针中。

每个对象有一个64位指针,这64位被分为:

  • 18位:预留给以后使用;
  • 1位:Finalizable标识,与并发引用处理有关,表示这个对象只能通过finalizer才能访问;
  • 1位:Remapped标识,设置此位的值后,表示对象已重映射,不再指向relocation set(relocation set表示需要GC的Region集合);
  • 1位:Marked1标识;
  • 1位:Marked0标识,和上面的Marked1都是标记对象用于辅助GC;
  • 42位:对象的地址(所以它可以支持2^42=4T内存):

为什么有2个mark标记?

每一个GC周期开始时,会交换使用的标记位,使上次GC周期中修正的已标记状态失效,所有引用都变成未标记。

GC周期1:使用mark0, 则周期结束所有引用mark标记都会成为01。

GC周期2:使用mark1, 则期待的mark标记10,所有引用都能被重新标记。

通过对配置ZGC后对象指针分析我们可知,对象指针必须是64位,那么ZGC就无法支持32位操作系统,同样的也就无法支持压缩指针了(CompressedOops,压缩指针也是32位)。

颜色指针的三大优势:

  1. 一个Region中的所有存活对象都被移走后,这个Region就可以被立即释放掉,因为它还有转发表。理论上,只要还有一个Region空闲,ZGC就能完成垃圾收集工作。
  2. 颜色指针有指针的“自愈”(Self-Healing)能力,这样子就减少了写屏障(例如三色标记中的增量更新或原始快照),只需要一个读屏障就可以解决问题,减少了内存屏障的使用数量。
  3. 颜色指针有着极大的扩展性,因为还有18位未使用,更有利于后续功能的扩展。

参考文章:https://wiki.openjdk.java.net/display/zgc/Main

http://cr.openjdk.java.net/~pliden/slides/ZGC-Jfokus-2018.pdf

#JVM
JVM垃圾收集器三:G1(Garbage First)
JVM调优之常用的调优指令

← JVM垃圾收集器三:G1(Garbage First) JVM调优之常用的调优指令→

最近更新
01
otter二次开发-支持按目标端主键索引Load数据
08-03
02
mvnw简介
06-21
03
gor流量复制工具
06-03
更多文章>
Theme by Vdoing | Copyright © 2022-2024 元月 | 粤ICP备2022071877号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式