开发者社区> 田埂、> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

JVM垃圾收集-ZGC的染色指针

简介: 垃圾收集是回收以前分配的内存的机制, 以便将来的内存分配可以重用它。
+关注继续查看

前言:

🥂介绍染色指针之前,大家先回顾以下上一篇文章 《JVM垃圾收集-三色标记》,大部分追踪式垃圾收集器在并发标记阶段都采用了三色标记技术。但也有例外,比如:ZGC收集器有一个标志性的设计,就是采用了染色指针技术(Colored Pointer,其他类似的技术中可能将它称为Tag Pointer或者Version Pointer)。下面就来介绍一下染色指针。

应用场景

🌴🌴之前,如果我们要在对象上存储一些额外的、只供收集器或者虚拟机本身使用的数据,通常会在对象头中增加额外的存储字段,如对象的哈希码、分代年龄、锁记录等就是这样存储的。比如 64 位的 JVM,对象头的 Mark Word 中保存的信息如下图:

jm1.png

🎈这种记录方式在有对象访问的场景下是很自然流畅的,不会有什么额外负担。但如果有一些对象根本就不会去访问它,但又希望得知该对象的某些信息的场景呢?

我们就有这样的场景——追踪式收集算法的标记阶段就可能存在只跟指针打交道而不必涉及指针所引用的对象本身的场景。

🌰例如 对象标记的过程中需要给对象打上三色标记,这些标记本质上就只和对象的引用有关,而与对象本身无关——某个对象只有它的引用关系能决定它存活与否,对象上其他所有的属性都不能够影响它的存活判定结果。

👩HotSpot虚拟机的几种收集器有不同的标记实现方案:

  • 📍 把标记直接记录在对象头上(Serial收集器)
  • 📍 把标记记录在与对象相互独立的数据结构上(G1、Shenandoah使用了一种相当于堆内存的1/64大小的,称为BitMap的结构来记录标记信息)
  • 📍 ZGC的染色指针直接把标记信息记在引用对象的指针上(这个时候,与其说可达性分析是遍历对象图来标记对象,还不如说是遍历“引用图”来标记“引用”了。)


染色指针

染色指针是一种直接将少量额外的信息存储在指针上的技术。在 64 位 Linux 中,对象指针是 64 位,如下图:

jm2.png

👉🏻在这个 64 位的指针上,高 18 位都是 0,暂时不用来寻址。剩余的 46 位指针所能支持内存可以达到 64TB ,这可以满足多数大型服务器的需要了。不过 ZGC 并没有把 46 位都用来保存对象信息,而是用高 4 位保存了四个标志位,导致 ZGC 可以管理的最大内存不超过 4 TB 。

⭐⭐通过这四个标志位,JVM 可以从指针上直接看到对象的三色标记状态(Marked0、Marked1)、是否进入了重分配集(Remapped)、是否需要通过 finalize 方法来访问到(Finalizable)等信息。

无需进行对象访问就可以获得 GC 信息,这大大提高了 GC 效率。 🚀🚀🚀

🍺可以看到染色指针的优点已经很明显了。不过,要使用染色指针有一个必须解决的前置问题:Java虚拟机作为一个普普通通的进程,这样随意重新定义内存中某些指针的其中几位,操作系统是否支持?处理器是否支持?🤷‍

👩🏻‍程序代码最终都要转换为机器指令流交付给处理器去执行,处理器可不会管指令流中的指针哪部分存的是标志位,哪部分才是真正的寻址地址,只会把整个指针都视作一个内存地址来对待。

🎈在我们常用的x86-64平台上是不支持重新定义机器指令的,ZGC设计者们就采用了虚拟内存映射技术来解决这个问题。


虚拟内存映射

🍬在x86平台上,处理器会使用分页管理机制把线性地址空间物理地址空间分别划分为大小相同的块,这样的内存块被称为“页”(Page)。通过在线性虚拟空间的页与物理地址空间的页之间建立的映射表,分页管理机制会进行线性地址到物理地址空间的映射,完成线性地址到物理地址的转换。


✨简单的理解为:用 mmap 把不同的虚拟内存地址映射到同一个物理内存地址上。 如下图所示:

jm3.png

🍋ZGC 为了解决上面的寻址地址问题,使用了虚拟内存映射技术,把同一块儿物理内存映射为 Marked0、Marked1 和 Remapped 三个虚拟内存

🍹当应用程序创建对象时,会在堆上申请一个虚拟地址,这时 ZGC 会为这个对象在 Marked0、Marked1 和 Remapped 这三个视图空间分别申请一个虚拟地址,这三个虚拟地址映射到同一个物理地址。

🍦Marked0、Marked1 和 Remapped 这三个虚拟内存作为 ZGC 的三个视图空间,在同一个时间点内只能有一个有效。ZGC 就是通过这三个视图空间的切换,来完成并发的垃圾回收。

🙇好了关于染色指针的就介绍到这里,大家有什么疑问欢迎评论区讨论。

PS: 在 JDK 15 中 ,已经可以通过指令 –XX:+UseZGC 来启用采用染色指针技术的 ZGC收集器了。
🚀🚀🚀

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
【JVM进阶之路】六:垃圾收集理论和算法
【JVM进阶之路】六:垃圾收集理论和算法
0 0
JVM垃圾收集
本博客为《深入理解java虚拟机》的学习笔记所以大部分内容来自此书。 一 是否可以回收 Java中对象能否被回收取决于对象是“死”还是“活”下面我们就介绍一下判定算法。
1295 0
java面试-深入理解JVM(三)——垃圾收集策略详解
Java虚拟机的内存模型分为五个部分,分别是:程序计数器、Java虚拟机栈、本地方法栈、堆、方法区。
1243 0
深入理解JVM(三)——垃圾收集策略详解
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34173549/article/details/79612610 Java虚拟机的内存模型分为五个部分,分别是:程序计数器、Java虚拟机栈、本地方法栈、堆、方法区。
928 0
JVM垃圾收集(GC)
参考文献:周志明《深入理解Java虚拟机》第二版 因为 Java 具有自动垃圾回收机制,所以,垃圾收集(Garbage Collection,GC),是 Java 技术的核心之一,是...
1096 0
JVM深入学习笔记四:JVM垃圾收集和内存分配
<p>1. 垃圾判断算法</p> <p><span style="white-space:pre"></span>引用计数法,    给对象添加引用计数器,每有一个引用则+1, 没有则-1,为0为已死。python就是使用这种算法。  但是不能解决循环引用的问题。</p> <p><span style="white-space:pre"></span>根搜索算法。     从根开始向下
1108 0
JNI用C加载JDK产生JVM虚拟机,并运行JAVA类main函数(MACOS/LINUX/WINDOWS)
JNI用C加载JDK产生JVM虚拟机,并运行JAVA类main函数(MACOS/LINUX/WINDOWS)
0 0
JVM篇【Java源文件和Class字节码文件对比】
JVM篇【Java源文件和Class字节码文件对比】
0 0
+关注
田埂、
不惊于荣辱,不借于鼓吹,正余之心,穷于之力
文章
问答
文章排行榜
最热
最新
相关电子书
更多
JVM实战
立即下载
JVM的GC
立即下载
基于JVM的脚本语言开发、运用实践
立即下载