ZGC垃圾回收器
ZGC
Z Garbage Collector,ZGC 是从 JDK11 中引入的一种新的支持弹性伸缩和低延迟垃圾收集器
G1 设计上的特点,导致存在以下问题:
停顿时间过长
通常 G1 的停顿时间要达到几十到几百毫秒;这个数字其实已经非常小了,但是我们知道垃圾回收发生导致应用程序在这几十或者几百毫秒中不能提供服务,在某些场景中,特别是对用户体验有较高要求的情况下不能满足实际需求
内存利用率不高
通常引用关系的处理需要额外消耗内存,一般占整个内存的 1%~20%
左右
支持的内存空间有限
不适用于超大内存的系统,特别是在内存容量高于 100GB 的系统中,会因内存过大而导致停顿时间增长
ZGC 四大目标
- 支持
TB
级内存 - 停顿时间控制在
10ms
之内 - 奠定未来 GC 特性的基础
- 对程序吞吐量影响小于
15%
Oracle 官方提到了它最大的优点是:它的停顿时间不会随着堆的增大而增长!也就是说,几十
G
堆的停顿时间是10ms
以下,几百G
甚至上T
堆的停顿时间也是10ms
以下
ZGC 特点
- ZGC 最典型的特性是它是一款并发(concurrent)的 GC
- 它可以标记内存,复制和迁移(relocate)内存,所有的操作都是并发的,同时它有一个并发的引用处理器
- 其它的垃圾收集器都是使用
store barriers
,ZGC 使用load barriers
- ZGC 可以更加灵活的配置大小和策略,相比于 G1,它可以更好的处理非常大(very large)对象的释放
- ZGC 只有一代,没有新生代,老年代什么的
- ZGC 依赖
NUMA-aware(非均衡存储器访问)
- parse 时间在
10ms
以内 → JDK16 以后,ZGC 的停顿时间为O(1)
,不会超过1ms
- 在
JDK14
之前,ZGC 只能用于 Linux 上,现在也可以使用在windows
上了 - 不支持压缩类指针与压缩指针 →
JDK15
以后开始支持压缩类指针
ZGC 内存布局
基于 Region 内存布局的,暂时不设分代的,使用了读屏障、颜色指针等技术来实现可并发的标记-整理算法的,以低延迟为首要目标的一款垃圾收集器
ZGC 的 Region 分为大、中、小三类容量:
小型 Region(Small Region)
容量固定为 2MB
,用于放置小于 256KB
的小对象
中型 Region(Medium Region)
容量固定为 32MB
,用于放置大于等于 256KB
但小于 4MB
的对象
大型 Region(Large Region)
容量不固定,可以动态变化,但必须为 2MB
的整数倍,用于放置 4MB
或以上的大对象
NUMA-aware
UMA
UMA 即 Uniform Memory Access Architecture,UMA 表示内存只有一块,所有 CPU 都去访问这一块内存,那么就会存在竞争问题(争夺内存总线访问权),有竞争就会有锁,有锁效率就会受到影响,而且 CPU 核心数越多,竞争就越激烈
NUMA
Non Uniform Memory Access Architecture,NUMA 的话每个 CPU 对应有一块内存,且这块内存在主板上离这个 CPU 是最近的,每个 CPU 优先访问这块内存,那效率自然就提高了
颜色指针
HotSpot 的垃圾收集器,有几种不同的标记实现方案:
- 把标记直接记录在对象头上(Serial 收集器)
- 把标记记录在于对象相互独立的数据结构上,G1 使用了一种
BitMap
的结构来记录标记信息 - bitmap 堆的
1/64
Colored Pointers,即颜色指针,染色指针是一种直接将少量额外的信息存储在指针上的技术,ZGC 的 GC 信息保存在指针中。每个对象有一个 64 位指针,18 位,预留给以后使用
地址视图的状态
1位
Finalizable 标识,此位与并发引用处理有关,它表示这个对象只能通过 finalizer 才能访问,当前的对象正在回收
1位
Remapped 标识,在垃圾回收开始前视图是 Remapped,正在标记
1位
Marked1 标识,每一个 GC 周期开始时,会交换使用的标记位,使上次 GC 周期中修正的已标记状态失效,所有引用都变成未标记,GC 周期1:使用 mark0,则周期结束所有引用 mark 标记都会成为 01。GC 周期2:使用 mark1,则期待的 mark 标记 10,所有引用都能被重新标记
1位
Marked0 标识,和上面的 Marked1 都是标记对象用于辅助 GC,在标记阶段结束之后,对象的地址视图要么是 M0(活跃),要么是 Remapped(垃圾)
42位
对象的地址(所以它可以支持 2^42=4T
内存)JDK13 16TB 低 44 位
ZGC 将其高 4 位提取出来存储四个标志信息,通过这些标志虚拟机就可以直接从指针中看到引用对象的三色标记状态,是否进入了重分配集(Marked0、Marked1),是否被移动过(Remapped),是否只能通过 finalize() 方法才能被访问到(Finalizable)
优势
颜色指针可以使得一旦某个 Region 的存活对象被移走之后,这个 Region 立即就能够被释放和重用掉,而不必等待整个堆中所有指令向该 Region 的引用都被修正后才能清理,染色指针可以大幅减少在垃圾收集过程中内存屏障的使用数量,设置内存屏障,尤其是在写屏障的目的通常是为了记录对象引用的变动情况。如果将这些信息直接维护在指针中,显然就可以省去一些专门的记录操作,染色指针可以作为一种可扩展的存储结构用来记录更多与对象标记、重定位过程相关的数据,以便日后进一步提高性能
回收过程
并发标记 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)能力
并发重映射 Concurrent Remap
重映射所做的就是修正整个堆中指向重分配集中旧对象的所有引用,但是 ZGC 中对象引用存在 “自愈” 功能,所以这个重映射操作并不是很迫切,ZGC 的并发映射并不是以一个必须要 “迫切” 去完成的任务。ZGC 很巧妙地把并发重映射阶段要做的工作,合并到下一次垃圾收集循环中的并发标记阶段里去完成,他们都是要遍历所有对象的,这样合并节省了一次遍历的开销
读屏障
读一个对象的时候,会加上 load barrier
,检测是不是 bad color,mark / relocate / remap,等完成拿到新地址,再返回
ZGC 的优劣势
缺点
浮动垃圾
当 ZGC 准备要对一个很大的堆做一次完整的并发收集,持续十分钟以上,由于应用的对象分配速率很高,将创造大量的新对象,这些新对象很难进入当次收集的标记范围,通常就只能全部作为存活对象来看,目前唯一的办法就是尽可能地去增加堆容量大小,获取更多喘息的时间。但若要从根本上解决,还是需要引入分代收集,让新生对象都在一个专门的区域中创建,然后针对这个区域进行更频繁、更快的收集
优点
高吞吐量、低延迟
ZGC 是支持 “NUMA-Aware” 的内存分配。NUMA(Non-Uniform Memory Access,非统一内存访问架构)是一种多处理器或多核处理器计算机所设计的内存架构。ZGC 默认支持 NUMA 架构,在创建对象时,根据当前线程在哪个 CPU 执行,优先在靠近这个 CPU 的内存进行分配,这样可以显著的提高性能,在 SPEC JBB 2005 基准测试里获得 40% 的提升
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具