一文带你彻底弄懂ZGC

news2024/12/19 14:43:18

1 推荐的文章

1.1 必看

干掉1ms以内的Java垃圾收集器ZGC到底是个什么东西?

1.2 选看

ZGC有什么缺点?

2 疑问【皆来自上面两篇文章】

2.1 什么使得用户线程工作的同时,让垃圾收集器可以回收垃圾-读写屏障

ZGC (Z Garbage Collector) 和读写屏障:

ZGC确实使用了读写屏障。读写屏障是一种在对象读取和写入操作时自动执行的额外操作,用于维护垃圾收集器的某些属性。

在ZGC中,读写屏障主要用于两个目的:

  • 并发可重定位: ZGC可以在应用线程运行时移动对象,这要求在每次对象访问时都进行检查,以确保访问的是对象的最新副本。读写屏障用于在对象访问时执行这些检查和必要的调整。

  • 标记: 和其他垃圾收集器一样,ZGC需要标记活对象。它使用读写屏障在对象访问时进行标记。

通过使用读写屏障,ZGC能够在应用线程运行时执行垃圾收集的大部分工作,从而实现极低的停顿时间。

2.2 为什么当GC信息存储在对象头上时,无法立即重用对应的内存空间?【接2.1的问题】

摘自:

如图,这个对象在第二次GC周期开始的时候,地址视图还是M0。如果第二次GC的标记阶段还切到M0视图的话,就不能区分出对象是活跃的,还是上一次垃圾回收标记过的。这个时候,第二次GC周期的标记阶段切到M1视图的话就可以区分了,此时这3个地址视图代表的含义是:

M1:本次垃圾回收中识别的活跃对象。
M0:前一次垃圾回收的标记阶段被标记过的活跃对象,对象在转移阶段未被转移,但是在本次垃圾回收中被识别为不活跃对象。
Remapped:前一次垃圾回收的转移阶段发生转移的对象或者是被应用程序线程访问的对象,但是在本次垃圾回收中被识别为不活跃对象。
现在,我们可以回答“使用地址视图和染色指针有什么好处”这个问题了

使用地址视图和染色指针可以加快标记和转移的速度。以前的垃圾回收器通过修改对象头的标记位来标记GC信息,这是有内存存取访问的,而ZGC通过地址视图和染色指针技术,无需任何对象访问,只需要设置地址中对应的标志位即可。这就是ZGC在标记和转移阶段速度更快的原因。

当GC信息不再存储在对象头上时而存在引用指针上时,当确定一个对象已经无用的时候,可以立即重用对应的内存空间,这是把GC信息放到对象头所做不到的。

我的理解:参考传统的cms或者g1收集器,这种对象头存储了gc信息,也就意味着在垃圾收集阶段,必须产生STW,让用户线程停止工作,直到垃圾收集阶段结束后,被收集的空闲空间才能被用户线程重用。在zgc阶段,垃圾收集和用户线程可以并发的操作一个对象,那么就必须让gc信息独立于对象头存储,这样即使gc线程占用了这个垃圾对象,用户线程还可以通过独立存储的染色指针了解到这个对象的垃圾情况,一旦知道被收集或者发生了转移,用户线程通过读写屏障机制可以立马感知到。

当垃圾收集器将GC信息存储在对象头上时,每次访问对象都需要检查这些信息,以确定对象是否处于活动状态、是否已被标记为垃圾等。这种设计有几个缺点,其中之一就是在对象变成垃圾并且确定可以回收其占用的内存空间之后,不能立即重用这些内存空间。

这是因为即使一个对象已经确定为垃圾,其他线程可能仍然持有到这个对象的引用,并可能尝试访问它。如果垃圾收集器立即回收并重用这块内存空间,这些访问可能会导致未定义行为,因为内存可能已经被重新分配并用于其他目的。

为了安全地回收内存,垃圾收集器需要确保没有任何线程可以再访问到被判定为垃圾的对象。这通常意味着需要等到所有可能访问到对象的线程都到达了一个安全点(safe point),在这个点上它们不会再访问到垃圾对象。这个过程可能会引入额外的停顿时间,尤其是在多线程环境中。

另一方面,ZGC通过使用地址视图和染色指针技术,将GC信息存储在引用指针上,而不是对象头上。这样,即使一个对象变成了垃圾,其他线程持有的引用仍然可以通过地址视图和染色指针的转换来访问到这个对象,直到垃圾收集器确定可以安全地回收和重用这块内存空间。这种设计允许ZGC在应用线程运行时执行大部分垃圾收集工作,从而减少停顿时间,并且能够更快地回收和重用内存空间。

2.3 压缩指针技术

2.3.1 什么是压缩指针技术

这是一种内存优化技术,通过减小对象引用的大小来减少内存占用和提高性能。在启用压缩指针的情况下,对象引用不再直接存储对象的实际内存地址,而是存储一个相对于某个基地址的偏移量。这允许使用更小的数据类型来存储引用,从而减小其大小。

2.3.2 染色指针和压缩指针的区别,染色指针有无用到压缩指针技术

Z Garbage Collector (ZGC) 是一种低延迟的垃圾收集器,自从在JDK 11中首次引入以来,它确实经历了大量的发展和改进。

染色指针和压缩指针是两种不同的技术,但是染色指针中存储的地址信息可以使用压缩指针技术:

  • 染色指针: ZGC使用染色指针来存储关于对象的元数据(如标记信息、转发指针等)。染色指针通过在指针的低位或高位添加额外的位来实现,这些位用于存储垃圾收集器需要的信息。这种技术允许ZGC在不访问对象本身的情况下快速检索这些信息,从而减少延迟。

  • 压缩指针: 这是一种内存优化技术,通过减小对象引用的大小来减少内存占用和提高性能。在启用压缩指针的情况下,对象引用不再直接存储对象的实际内存地址,而是存储一个相对于某个基地址的偏移量。这允许使用更小的数据类型来存储引用,从而减小其大小。

虽然染色指针和压缩指针都涉及对指针的操作,但它们解决的问题和实现的方式是不同的。ZGC确实使用了染色指针技术,但这和压缩指针技术是分开的。ZGC在JDK 15中增加了对压缩类指针的支持,这意味着即使在使用ZGC的情况下,也可以利用压缩指针技术来减小内存占用和提高性能。

2.3.3 jdk15中,压缩指针被用在了哪个地方,染色指针有没有用到这种压缩技术

JDK 15中的压缩指针和染色指针:

  • 压缩指针: 在JDK 15中,ZGC增加了对压缩类指针(Compressed Class Pointers)的支持。这意味着即使在使用ZGC时,也可以利用压缩指针技术来减小Java堆对象的内存占用。压缩类指针主要用于优化对象头中的类元数据指针的存储。通过将这些指针存储为相对于Java堆的某个基地址的偏移量,而不是完整的64位地址,可以减小对象头的大小,从而减小整体的内存占用。

  • 染色指针: ZGC使用染色指针来存储关于对象的元数据,如标记信息和转发指针。染色指针通过在指针的一部分位上存储这些额外的信息来实现。这并不是压缩指针技术,但它是一种利用指针额外位的技术。染色指针主要用于加速垃圾收集过程,而不是为了减小内存占用。

总的来说,虽然压缩指针和染色指针都涉及对指针的操作,但它们解决的问题和实现的方式是不同的。压缩指针用于减小内存占用,而染色指针用于加速垃圾收集过程。

2.3.4 染色指针中存储的是对象的位置,这个位置信息有可能过时是吗?

是的,染色指针中存储的位置信息可能会过时。当垃圾收集器决定移动一个对象时,它会更新对象的位置,并在原始位置留下一个转发指针,指向对象的新位置。如果染色指针中的位置信息过时,加载屏障将介入,使用转发指针来找到对象的当前位置,并更新染色指针以反映最新状态。

2.4 ZGC通过在并发阶段执行大部分工作来实现极低的停顿时间,如何实现的,具体讲讲

Z Garbage Collector (ZGC) 是一种低延迟的垃圾收集器,它通过在并发阶段执行大部分的垃圾收集工作来实现极低的停顿时间。下面是ZGC如何实现这一目标的具体细节:

2.4.1 并发执行

ZGC的大多数阶段都是并发执行的,意味着这些阶段可以与应用线程同时运行,而不需要停止应用线程。这包括标记阶段、重分配阶段、重映射阶段和清理阶段。通过在并发阶段执行这些工作,ZGC能够显著减少停顿时间。

2.4.2 染色指针和加载屏障

ZGC使用染色指针技术来存储对象的元数据,如标记信息和转发指针。这意味着这些信息存储在指针本身中,而不是在对象头中。为了支持这种技术,ZGC使用了加载屏障(Load Barrier),这是一种在读取对象引用时自动执行的操作。

当应用线程尝试通过染色指针访问对象时,加载屏障会介入并执行必要的操作,如解析转发指针以找到对象的当前位置,或者更新染色指针以反映对象的最新状态。这确保了即使在垃圾收集过程中对象被移动,应用线程也能够无缝地访问对象。

2.4.3 分代收集和区域化内存

虽然ZGC不是一个传统的分代垃圾收集器,但它采用了一种类似分代收集的方法,将内存划分为多个区域,并根据对象的生命周期将其分配到不同的区域中。这允许ZGC有效地管理内存,并减少需要在每次垃圾收集周期中处理的对象数量。

2.4.4 并发可重定位

ZGC能够在应用线程运行时移动对象,这是通过并发重分配阶段实现的。在这个阶段,ZGC会识别出需要移动的对象,并将它们复制到新的内存位置,同时更新所有指向这些对象的引用。

这种并发可重定位的能力是ZGC实现低停顿时间的关键。它允许ZGC在应用线程运行时执行大量的内存压缩和碎片整理工作,从而减少了需要在停顿阶段执行的工作量。

2.5 zgc加载屏障

2.5.1 什么是加载屏障?

2.5.2 加载屏障的添加时机?

加载屏障是在读取对象引用时自动添加的。在ZGC中,每次应用线程尝试通过染色指针访问对象时,加载屏障都会介入。加载屏障的目的是确保即使在垃圾收集过程中对象被移动,应用线程也能够无缝地访问对象。

2.5.3 转发指针的存储位置:

转发指针通常存储在对象被移动前的原始内存位置。当对象被移动到新的位置时,原始位置上的内存会被更新为一个转发指针,指向对象的新位置。

2.5.4 用户线程是否参与移动对象的操作:

用户线程不直接参与移动对象的操作。对象的移动是由垃圾收集器在并发重分配阶段执行的。然而,用户线程在通过染色指针访问对象时,可能会触发加载屏障,加载屏障可能会执行一些与对象移动相关的操作,如解析转发指针和更新染色指针。

2.5.5 转移的对象是否都是存活的对象:

是的,转移的对象通常都是存活的对象。垃圾收集器在标记阶段确定哪些对象是存活的,然后在重分配阶段只移动这些存活的对象。目标是将存活的对象集中到连续的内存区域中,从而减少内存碎片并提高内存使用效率。不存活的对象将被垃圾收集器回收,它们占用的内存空间将被释放。

2.6 zgc中的区域也是逻辑划分的吗,像g1一样分成多个大小均等的子区域?

ZGC的内存管理与G1有所不同。ZGC不是将堆划分为多个大小均等的子区域,而是使用一种称为“Colored Pointers and Load Barriers”的技术来管理内存。ZGC的内存是动态划分的,它使用大的内存页来管理堆空间,并在需要时动态地分配和释放这些内存页。这种设计使得ZGC能够更灵活地管理内存,减少内存碎片,并提高内存利用率。

2.7 zgc的生命周期

在这里插入图片描述

2.7.1 ZGC的垃圾收集阶段

  • 初始标记(Initial Mark):

    • 用户线程:继续运行,但是会受到一些停顿的影响,因为ZGC需要标记所有从GC根直接可达的对象。
    • GC线程:标记所有从GC根直接可达的对象,并为并发标记阶段做一些准备工作。
  • 并发标记/对象重定位(Concurrent Mark/Relocation):

    • 用户线程:继续运行,并且在访问对象时可能会触发加载屏障,以帮助标记和重定位对象。
    • GC线程:并发地标记堆中所有可达的对象,并开始重定位一些对象到新的内存位置。
  • 再标记(Remark):

    • 用户线程:可能会受到停顿的影响,因为ZGC需要完成标记过程,并处理一些遗留的工作。
    • GC线程:完成标记过程,处理并发阶段中遗留的一些工作。
  • 并发转移准备(Concurrent Relocation Preparation):

    • 用户线程:继续运行,并且在访问对象时可能会触发加载屏障。
    • GC线程:准备进行对象的并发转移,包括确定哪些对象需要被移动。
  • 初始转移(Initial Relocation):

    • 用户线程:继续运行,但是会受到一些停顿的影响,因为ZGC需要开始移动对象。
    • GC线程:开始移动一些对象到新的内存位置。
  • 并发转移(Concurrent Relocation):

    • 用户线程:继续运行,并且在访问对象时可能会触发加载屏障,以帮助重定位对象。
    • GC线程:并发地移动剩余的对象到新的内存位置。

这个描述提供了一个大致的概览,但是需要注意的是,ZGC的具体实现和行为可能会随着不同版本的JDK而变化。

2.7.2 再标记阶段的遗留工作

在再标记(Remark)阶段,ZGC完成了并发标记阶段可能遗留下来的一些工作。这些工作可能包括:

  • 处理并发标记阶段中遗留的标记任务。
  • 处理并发阶段中新产生的引用关系。
  • 更新和处理内部数据结构,为后续的转移阶段做准备。

2.7.3 为什么再标记和初始转移也涉及到找gc roots动作

  • 初始标记(Initial Mark): 这个阶段确实涉及到扫描所有的GC Roots,以标记所有从GC Roots直接可达的对象。这个阶段的耗时与GC Roots的数量成正比。

  • 再标记(Remark): 这个阶段可能需要再次处理GC Roots,以确保在并发标记阶段新产生的引用关系得到正确处理。此外,再标记阶段还需要完成一些其他的清理和准备工作,以确保转移阶段能够正确执行。

  • 初始转移(Initial Relocation): 在初始转移(Initial Relocation)阶段,ZGC开始移动对象到新的内存位置。处理GC Roots的原因并不是为了防止转移后的空间被占用,而是为了更新指向即将被移动对象的引用。GC Roots是程序运行中的一组引用,它们直接指向堆中的对象。当对象被移动时,这些直接指向对象的引用也必须被更新,以确保它们指向对象的新位置。如果不更新这些引用,程序可能会尝试访问已经不再有效的内存位置,导致错误。

ZGC的设计目标是尽量减少STW阶段的影响,以实现低延迟。虽然初始标记和初始转移阶段的确需要处理GC Roots,但这些阶段通常耗时非常短。再标记阶段虽然可能涉及到更多的工作,但ZGC通过优化和并行处理尽量减少了这个阶段的停顿时间。

2.7.4 每一个阶段有固定的时间段吗?

在初始转移(Initial Relocation)阶段,ZGC开始移动对象到新的内存位置。处理GC Roots的原因并不是为了防止转移后的空间被占用,而是为了更新指向即将被移动对象的引用。GC Roots是程序运行中的一组引用,它们直接指向堆中的对象。当对象被移动时,这些直接指向对象的引用也必须被更新,以确保它们指向对象的新位置。如果不更新这些引用,程序可能会尝试访问已经不再有效的内存位置,导致错误。

2.7.5 垃圾是在转移阶段被回收的吗还是默认被新的对象覆盖就行了?

在ZGC中,垃圾(不再被引用的对象)是在转移阶段间接回收的。具体来说,ZGC通过标记-重定位的方式工作。在标记阶段,它标记出所有存活的对象。在转移阶段,它只移动这些存活的对象到新的内存位置,并更新所有指向这些对象的引用。没有被标记的对象(即垃圾)不会被移动,它们占用的内存空间在转移后变得空闲,可以在后续的内存分配中被重用。因此,垃圾对象的内存是在新对象分配时被覆盖的。

2.8 zgc的缺点

2.8.1 ZGC时Java进程占用三倍内存问题:由于ZGC着色指针把内存空间映射了3个虚拟地址,使得TOP/PS等命令查看占用内存时看到Java进程占用内存过大。此问题不影响操作系统,但是会影响到监控运维工具,需要注意。分析一下是这样的吗

Z Garbage Collector (ZGC) 使用了一种称为“着色指针”(Colored Pointers)的技术来管理堆内存和实现快速的垃圾收集。这种技术涉及到将每个内存页映射到多个虚拟地址空间中,通常是三个。这三个地址空间分别用于不同的目的,如标记活对象、重定位对象等。

这种内存映射方式确实会导致操作系统报告的Java进程内存占用量增加,因为同一块物理内存被映射到了多个虚拟地址空间。然而,这并不意味着Java进程实际上消耗了更多的物理内存。物理内存的实际使用量并没有增加,只是因为多次映射导致在虚拟地址空间中的占用看起来更大。

这种情况可能会对一些监控和运维工具造成影响,因为这些工具可能会根据操作系统报告的内存占用量来生成警告或者报告。如果这些工具没有针对ZGC的内存管理方式进行优化,它们可能会误报Java进程的内存占用过高。

为了准确监控和管理使用ZGC的Java应用,运维团队可能需要更新或配置他们的监控工具,以正确解释ZGC的内存使用情况。这可能包括使用Java自带的工具(如jstat、jmap等)或者其他了解ZGC工作原理的第三方工具来获取更准确的内存使用信息。

2.8.2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1121680.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【瑞吉外卖部分功能补充】

瑞吉外卖部分功能补充 菜品的启售和停售 在浏览器控制台点击对应功能后可以看到前端发送的请求是:http://localhost:9999/dish/status/1?ids1413342036832100354,请求方式为POST。 接收到前端参数后,进行controller层代码补全&#xff0c…

简单说明反射和new的区别和反射的使用代码展示

目录 1.反射的认识 2.反射和new的区别 3.反射的使用代码展示 4.反射优点和缺点 1.反射的认识 反射是Java语言的一种机制,它允许程序在运行时检查和操作类、方法、字段等信息,而不需要提前知道它们的具体定义。通过反射,我们可以在运行时动…

直接插入排序——希尔排序

排序——先写单个——再衍生到整体 单个插入排序——在插入前数组里面的数是有序的,然后来了一个数据,就要用这个数组从后往前和这个数比较, 整体的话就是,end从0开始,循环n-1次 void TnsertSort(int* a,int n) {in…

QML之Repeater 控件使用

Repeater 控件是 重复作用 根据 model中的index 数量进行重复 废话不说 直接看如何用 当model 为数字时 Rectangle{height: 1200width: 500visible: trueanchors.fill: parentColumn{spacing: 20Repeater{model: 10delegate: Rectangle{width: 60height: 20color: index%2 …

VulnHub ch4inrulz: 1.0.1

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏…

【网络编程】应用层——HTTP协议

文章目录 一、HTTP协议简介二、认识URL三、HTTP协议格式1. HTTP请求协议格式2. HTTP响应协议格式 三、构建HTTP请求和响应四、HTTP的方法五、HTTP的状态码六、HTTP常见的Header七、Cookie和Session 一、HTTP协议简介 HTTP 协议 是 Hyper Text Transfer Protocol(超文…

苹果ios打包出来的ipa应用APP怎么不能安装?多种安装不上的原因排查

亲爱的同学们,非常高兴能和同学们一起探讨关于苹果应用安装失败的问题。作为一个开发者,我们很可能会遇到这样的情况:开发好一个应用,兴致勃勃地想把它运行到手机上去测试,结果发现安装失败了。而此时,定位…

【2023_10_22计算机热点知识分享】:人工智能

最近计算机领域的热点话题之一是人工智能的发展。人工智能是一种能够模拟人类智能的技术,它可以通过机器学习、深度学习、自然语言处理等技术,实现语音识别、图像识别、自然语言处理等智能化的功能。人工智能技术的发展,正在深刻地改变着人类…

Docker概述、部署、镜像与容器管理

Docker概述、部署、镜像与容器操作 一、Docker是什么?1.1、Docker介绍1.2、Docker的设计宗旨1.3、容器运行条件1.4、容器与虚拟机的区别1.5、Docker核心概念1.5.1、镜像1.5.2、容器1.5.3、仓库 二、Docker部署三、Docker 镜像管理3.1、搜索镜像3.2、查看仓库中有哪些…

01-JVM 内存结构

JVM 内存结构 Java 虚拟机的内存空间分为 5 个部分: 程序计数器Java 虚拟机栈本地方法栈堆方法区 JDK 1.8 同 JDK 1.7 比,最大的差别就是:元数据区取代了永久代。元空间的本质和永久代类似,都是对 JVM 规范中方法区的实现。不过…

Redis --- 安装教程

Redis--- 特性,使用场景,安装 安装教程在Centos7.6下安装Redis5 特性在内存中存储数据可编程的扩展能力持久化集群高可用快速 应用场景实时数据存储作为缓存或者Session存储消息队列 安装教程 在Centos7.6下安装Redis5 1.安装scl源 yum install cento…

云原生微服务 第十章 Spring Cloud Alibaba 之 Nacos discovery

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 第七章 Spring Cloud 之 GateWay 第八章 Sprin…

STM32F4_网络通信(网口)

前言 STM32F4开发板上自带了网口。可以通过开发板自带的网口和LWIP实现:TCP服务器、TCP客服端、UDP以及WEB服务器等四个功能。 1. STM32 以太网简介 STM32F4 芯片自带以太网模块,该模块包括带有专用 DMA 控制器的 MAC 802.3(介质访问控制&am…

文心一言 VS 讯飞星火 VS chatgpt (118)-- 算法导论10.3 3题

三、用go语言,在ALLOCATE-OBJECT和 FREE-OBJECT过程的实现中,为什么不需要设置或重置对象的 prev 属性呢? 文心一言: 在 Go 语言中,ALLOCATE-OBJECT 和 FREE-OBJECT 过程的实现通常不需要显式地设置或重置对象的 prev 属性。这…

【MATLAB源码-第54期】基于白鲸优化算法(WOA)和遗传算法(GA)的栅格地图路径规划最短路径和适应度曲线对比。

操作环境: MATLAB 2022a 1、算法描述 ​1.白鲸优化算法(WOA): 白鲸优化算法是一种受白鲸捕食行为启发的优化算法。该算法模拟了白鲸群体捕食的策略和行为,用以寻找问题的最优解。其基本思想主要包括以下几点&#x…

Linux高性能服务器编程——ch7笔记

第7章 Linux服务器程序规范 7.1 日志 Linux提供rsyslogd守护进程接收用户进程输出的日志和内核日志。 应用程序使用syslog函数与rsyslogd守护进程通信。 void syslog(int priority, const char* message, …); openlog函数:改变syslog的默认输出方式。 setlogm…

【Java基础面试三十七】、说一说Java的异常机制

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。 面试官:说一说Java的异常机制 …

MIT 生物信息课程

youtube链接 Regulatory Genomics (Lecture 07): 这门课程介绍了基因调控的概念,涉及到基因的开启和关闭。这是生物信息学中的一个核心概念,对于理解整个生物网络至关重要。 Deep Learning for Regulatory Genomics (Lecture 08): 在了解了基因调控的基…

您账号或密码有误,请重新输入?

1、网站不让我进? 2、警告:声明未成年人不可轻易模仿!可刑 3、MYSQL函数特性是如何被黑客利用的? --- SQL 注入原理: 账号登录场景: --- 数据库概述: --- MYSQL系统库(默认): MYSQL数据…

关于计算机找不到vcomp140.dll无法继续执行怎么修复

在计算机使用过程中,我们可能会遇到各种问题,其中之一就是vcomp140.dll文件丢失。vcomp140.dll是一个动态链接库文件,它通常用于支持软件运行和系统功能。当这个文件丢失时,可能会导致程序无法正常运行,甚至系统出现错…