ZGC(Z Garbage Collector) 是 Oracle 在 JDK 11 中引入的一种超低延迟垃圾收集器,旨在为大规模应用提供高效的内存管理,尤其是在大内存(几十 GB 到数 TB)场景下。ZGC 的设计目标是将 GC 停顿时间控制在10ms以下,并且在内存规模增长时,GC 停顿时间不会显著增加。
ZGC 的特点
-
超低延迟:ZGC 的垃圾回收暂停时间非常短,通常小于 10 毫秒。相比传统垃圾收集器如 CMS 和 G1,它的暂停时间与堆大小无关,因此即便在大内存应用中,ZGC 也能保证很短的 GC 停顿时间。
-
高吞吐量:虽然 ZGC 主要以低延迟为目标,但它的吞吐量与其他 GC 如 G1 相比并没有明显劣势。
-
大堆支持:ZGC 可以很好地处理 TB 级别的堆内存,是处理大数据、大型应用场景下的理想选择。
-
并发标记和压缩:ZGC 几乎所有的工作都是并发执行的,垃圾回收的标记和对象的移动(压缩)都是在不停止应用线程的情况下进行的,这显著减少了对应用程序的影响。
-
染色指针(Colored Pointers):ZGC 采用了一种独特的 "染色指针" 技术,将 GC 状态信息编码到对象指针中,以便在对象访问时可以获取 GC 信息。
ZGC 工作流程
ZGC 的垃圾回收过程由四个主要阶段组成:
-
并发标记阶段(Concurrent Marking)
- 这一阶段是并发进行的,ZGC 会标记出所有可达的对象。ZGC 使用一种基于图的遍历算法,依次从 GC Roots 开始,递归遍历对象图,标记所有活动对象。与传统的 GC 不同,ZGC 在标记阶段几乎不会停止应用线程。
-
并发预备重定位阶段(Concurrent Prepare for Relocation)
- 这一阶段,ZGC 通过并发的方式来分析哪些区域需要被压缩(即进行对象的移动)。与其他 GC 不同,ZGC 将标记和压缩分为不同的阶段,因此可以减少停顿时间。
-
并发重定位阶段(Concurrent Relocation)
- 在这个阶段,ZGC 通过 "染色指针" 来支持并发的对象移动。它会在对象被访问时实时更新对象的地址。这样可以确保即使在对象移动期间,程序仍然可以访问这些对象。
-
短暂的暂停阶段(Stop-the-World Pause)
- 尽管 ZGC 几乎所有工作都是并发进行的,但它在整个垃圾收集过程中会有几个非常短暂的停顿。例如,ZGC 会在标记的初始阶段短暂停顿,以处理线程栈中的 GC Roots。另一个停顿是在对象移动之前的同步阶段。
ZGC 的核心技术
1. 染色指针(Colored Pointers)
ZGC 通过给对象的指针(地址)附加 "染色" 信息来追踪对象的状态。染色指针使用对象引用中的一部分位来存储元数据,例如:
- 对象是否已经被标记。
- 对象是否已经被压缩。
- 对象是否正在移动。
染色指针的一个关键好处是,它不需要额外的内存来存储元数据,可以高效地处理对象状态信息。
2. Load barriers(加载屏障)
ZGC 使用了一种叫做 "加载屏障" 的技术。加载屏障是一种轻量级机制,作用是在每次读取对象引用时,都会进行一次轻量级检查,确保该引用指向的是最新的地址,并根据需要更新对象引用。这使得 ZGC 可以在垃圾收集期间安全地移动对象,而不影响正在运行的应用。
3. 并发标记和压缩
ZGC 的标记和对象移动(压缩)是并发进行的。这意味着,即使在进行垃圾回收的过程中,应用程序也可以继续运行,而不会因为垃圾收集暂停而中断。传统的垃圾收集器通常会在标记和压缩过程中 "Stop-the-World",而 ZGC 的并发模型则极大地减少了停顿时间。
ZGC 与其他 GC 的对比
| 特性 | ZGC | G1 GC | CMS GC | Parallel GC |
|---|---|---|---|---|
| 主要目标 | 低延迟 | 低延迟,适中吞吐量 | 低延迟 | 高吞吐量 |
| 最大堆大小 | TB 级别 | 一般几百 GB | 一般几百 GB | 一般几百 GB |
| 暂停时间 | < 10ms,且与堆大小无关 | 短暂停时间,随着堆增长而增加 | 停顿较短,但可能出现 "浮动垃圾" | 停顿时间长 |
| 对象压缩 | 并发 | 混合模式 | 无压缩 | Stop-the-World 压缩 |
| 染色指针 | 有 | 无 | 无 | 无 |
使用 ZGC 的场景
ZGC 适用于以下场景:
- 超大堆内存应用:在内存需求达到几十 GB 到数 TB 级别的应用中,ZGC 能够提供低停顿的垃圾回收体验。
- 低延迟应用:对于金融系统、实时响应系统、大规模在线服务等对延迟非常敏感的场景,ZGC 的短暂停顿特性非常适合。
- 混合负载:ZGC 适合在有大数据处理、批量计算与交互式任务混合的负载中使用。
如何使用 ZGC
在启动 Java 应用时,可以通过以下 JVM 参数启用 ZGC:
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx<size> -Xms<size> -jar yourapp.jar
-XX:+UnlockExperimentalVMOptions:启用实验性 VM 选项(ZGC 是实验性特性,需显式启用)。-XX:+UseZGC:启用 ZGC 作为垃圾回收器。-Xmx和-Xms:分别设置最大和最小堆内存大小。
ZGC 的优缺点
优点:
- 低延迟:堆内存再大,ZGC 都可以保持极短的 GC 停顿时间,通常小于 10 毫秒。
- 并发标记与压缩:所有标记和压缩操作几乎都是并发进行,减少了 Stop-the-World 的时间。
- 大堆支持:ZGC 支持 TB 级别的大堆,在大数据处理场景中非常适用。
缺点:
- 实验性:尽管 ZGC 从 JDK 11 开始引入,但它仍然是一种实验性特性,在某些特殊场景下可能存在未被充分测试的行为。
- 吞吐量:尽管 ZGC 能保证极低的延迟,但与 Parallel GC 等主要关注吞吐量的收集器相比,吞吐量稍低,尤其是在某些极端负载下。
- 32位系统不支持:ZGC 仅支持 64 位系统,特别是 Linux、macOS 和 Windows 的 64 位版本。
总结
ZGC 是一种极具创新性的垃圾回收器,特别适合对延迟要求极高或堆内存极大的应用场景。通过其独特的染色指针和加载屏障机制,ZGC 实现了低停顿、并发标记和并发压缩的功能,保证了应用的实时性和高效性。
对于需要处理超大内存且对延迟敏感的 Java 应用程序,ZGC 提供了优异的垃圾回收解决方案。