jdk21颜色指针研究

三色标记相关(CMS,G1使用。ZGC使用染色指针)

1、当前HotSpot虚拟机对标记方案的实现各不相同,采用了包括:对象头标记、BitMap映射和染色指针等不同方法。

具体如下:

  • Serial、PS、ParNew、CMS:这些垃圾回收器都是直接将标记信息打在对象头上的,因此写入和读取标记需要时机访问堆中对象。
  • G1、Shenandoah:将标记信息记录在与对象独立的数据结构上,通常是一种BitMap的结构,一般相当于堆内存的1/64大小,占用内存较大。
  • ZGC:采用染色指针的方式,直接将标记信息存储在引用对象的指针上,从而实现遍历“引用图”来标记“引用”的效果,而不是遍历对象图来标记对象。

总之,理解染色指针首先要理解三色标记算法这个垃圾标记算法,三色标记算法会为对象打上白、灰、黑三种颜色。在ZGC之前的垃圾回收器中,颜色标记都是被打在对象头的MarkWord当中的,这样判断是否是垃圾需要去实际访问堆中对象。

而染色指针则可以将颜色标记直接记录在指针上,这样就省去了访问实际对象的过程。这样一来,垃圾标记阶段遍历的不再是对象图来标记垃圾,而是通过遍历“引用图”来标记垃圾,引用的对象便是堆中的对象。

三色标记算法是什么? 三色标记算法是根可达算法的一种实现方案,其目的是为了找出所有可达对象。

那些收集器在使用: CMS, G1,在使用,ZGC使用的是染色指针算法。

为什么要有三色标记算法? 因为传统的「标记-清除」算法效率太低,于是采用三色标记算法通过将对象分成白色、黑色、灰色,以及将整个过程拆分成「初始标记、并发标记、重新标记、并发清除」4 个过程,从而降低 GC 停顿时间。

三色标记算法有什么缺陷? 三色标记算法会产生多标和漏标问题,其中漏标问题最严重。漏标问题会导致本该存活的对象被回收,从而导致严重的程序问题。

漏标有什么解决方案? 漏标有两种解决方案,分别是:增量更新和原始快照方式。CMS 回收器采用了增量更新方式,G1 回收器采用了原始快照方式。

漏标哪种解决方案最好? 江湖传闻 G1 回收器的原始快照方式效率高,但没有确切的理论证明,且听且珍惜。

       白色集合:
                白色集合是已死对象的集合,集合内的对象在标记环节结束后将被清除回收。

      黑色集合:
                黑色集合,黑色对象的集合,黑色对象代表其根可达,是存活的对象,不可以被回收;黑色对象没有引用指向白色对象,只能指向灰色对象。

        灰色集合:
                灰色集合,灰色对象的集合,灰色的对象代表其被根可达的黑色对象引用,但是还没有扫描该灰色对象是否引用白色集合中的对象;因为灰色对象根可达,它不能被回收,而且所有灰色的对象在被垃圾回收器扫描后将被迁移到黑色集合。主要解决少标的问题。

 三色标记算法提炼
                1,从灰色集合中取出一个对象Obj。

                2,将对象Obj引用的对象移动到灰色集合,以确保Obj以及Obj引用的对象不被回收。

                3,将对象Obj移动到黑色集合。

                4,重复以上三步,直到灰色集合为空。

                因为所有不能根可达的对象被加入到白色集合,而且对象只能够从白色集合转移到灰色集合,从灰色集合转移到黑色集合,所以不可能有黑色对象引用指向白色对象

  

但仅仅将对象划分成三个颜色还不够,真正关键的是:实现根可达算法的时候,将整个过程拆分成了初始标记、并发标记、重新标记、并发清除四个阶段,所以一般目前现代化的收集器都是至少有这四个阶段。

  • 初始标记阶段,指的是标记 GCRoots 直接引用的节点,将它们标记为灰色,这个阶段需要 「Stop the World」。
  • 并发标记阶段,指的是从灰色节点开始,去扫描整个引用链,然后将它们标记为黑色,这个阶段不需要「Stop the World」。
  • 重新标记阶段,指的是去校正并发标记阶段的错误,这个阶段需要「Stop the World」。
  • 并发清除,指的是将已经确定为垃圾的对象清除掉,这个阶段不需要「Stop the World」。

对比一下「四阶段拆分」和「一段式」的实现方式,我们可以看出:通过将最耗时的引用链扫描剥离出来作为并发标记阶段,将其与用户线程并发执行,从而极大地降低了 GC 停顿时间。 但 GC 线程与用户线程并发执行,会带来新的问题:对象引用关系可能会发生变化,有可能发生多标和漏标问题。

染色指针的实现原理 (ZGC使用)

染色指针的结构

染色指针简单来说就是一种将额外少量的垃圾标记信息(颜色信息)存储在对象指针上的技术,在64 位操作系统中,对象指针的长度也是64位,染色指针的结构图如下:

在染色指针中,高18位都是0暂未使用,剩余的46位实际上是能支持64TB的内存的,但是目前来说计算机内存空间还没这么大。于是剩余的46位中,高4位用来保存了4个标志位,低42位置才是用来保存对象的指针,所以ZGC最大可以管理的内存不超过4TB。染色指针中4个标志位的具体作用如下:

  1. Marked 0和Marked 1标志位:
  • 作用: 用于表示对象的三色标记状态,通常用于垃圾收集算法中的标记阶段。
  • 意义: 提供了直观的对象垃圾收集状态,通过这两个标志位,JVM可以轻松地追踪对象的标记状态,即未标记、已标记(Marked 0或Marked 1)等。
  1. Remapped标志位:
  • 作用: 表示对象是否已经进入了重分配集,即是否需要在内存重分配时进行特殊处理。
  • 意义: 对于ZGC垃圾收集算法,该标志位的存在能够提供更高效的内存重分配,避免不必要的复制或移动操作,从而提高垃圾收集的性能。
  1. Finalizable标志位:
  • 作用: 标识对象是否需要通过finalize方法进行访问,即是否需要执行清理和释放资源的操作。
  • 意义: 允许JVM更灵活地处理对象的生命周期,根据Finalizable标志位的状态来判断是否触发finalize方法,这在一些需要资源释放的情景下尤为重要。

通过这四个标志位,JVM可以直接从对象的指针上获取关键的状态信息,而无需访问对象本身的其他属性,这种直接的标志位设计有助于提高垃圾收集的效率和性能。

指自愈指针(Self-Healing Pointers)

自愈指针(Self-Healing Pointers)是指一种用于在并发垃圾回收中进行引用修复的技术。这种技术的目的是在对象移动时,通过修改指针本身而不是对象的引用关系,来维护正确的引用关系,从而避免了对引用对象的访问和修改。

在垃圾回收的过程中,如果对象发生移动,原本指向该对象的引用关系就会失效。传统的垃圾回收器需要遍历对象图,修复所有指向移动对象的引用,这会带来一定的性能开销。而自愈指针技术通过直接修改指针来维护引用关系,减少了对对象的访问和修改,提高了并发性能。

在自愈指针技术中,指针的高位(通常是一些特定的位或字节)被用来存储额外的信息,例如对象的新地址、标记信息等。当对象移动时,只需要修改指针的高位信息,而不需要访问对象本身,从而实现引用的自愈。

这种技术通常应用于并发垃圾回收算法中,其中对象的移动是允许的,并发标记和并发移动阶段需要通过自愈指针来保证引用的正确性。ZGC(Z Garbage Collector)就是一种使用了自愈指针技术的垃圾回收器,它通过虚拟内存映射和染色指针来实现并发垃圾回收,减小了对引用修复的停顿时间。

染色指针的优势

  1. 即时回收空间: 当某个Region中的存活对象被成功移走后,该Region就能够立即释放和重用,而无需等待整个堆中所有指向该Region的引用都被修正。这意味着,理论上只要还有一个空闲的Region,ZGC就能完成垃圾收集。相比之下,Shenandoah需要等到更新阶段结束才能释放回收集中的Region,特别是在Region内的对象都存活时,需要1:1的空间才能完成收集。
  2. 减少内存屏障使用: 染色指针可以显著减少在垃圾收集过程中内存屏障的使用数量。ZGC仅使用了读屏障,而不需要其他类型的内存屏障。这有助于提高垃圾收集的效率和性能。
  3. 强大的扩展性: 染色指针具备强大的扩展性,可以作为一种可扩展的存储结构,用于记录与对象标记、重定位过程相关的更多数据。这为将来进一步提高性能提供了可能性,使ZGC能够灵活适应不同的场景和需求。

颜色指针实现案例:

ZGC 详解 - 简书

三色标记详情:

原文链接:https://blog.csdn.net/oJieSi/article/details/134758659

一文带你弄懂 JVM 三色标记算法!-腾讯云开发者社区-腾讯云

ZGC 详解 - 简书

  • 29
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值