ZGC 收集器原理

候选人小陈在面试字节 P7 时,面试官问道:

"ZGC 的核心设计是什么?"

小陈说:"ZGC 使用着色指针..."面试官追问:"着色指针是怎么工作的?"

小陈答不上来。面试官继续追问:"ZGC 为什么能做到 < 1ms 的停顿?"

小陈彻底卡住了...

一、核心问题:ZGC 收集器原理 🔴

1.1 问题拆解

第一层:着色指针(怎么实现的?)
  "ZGC 的着色指针是什么?"
  考察点:Colored Pointers、Marked/Remapped/Finalizable

第二层:并发执行(怎么做到的?)
  "ZGC 的并发标记和并发清理是怎么实现的?"
  考察点:读屏障 STW

第三层:停顿时间控制(怎么控制的?)
  "ZGC 为什么能做到停顿时间 < 1ms?"
  考察点:Roots 数量固定

1.2 ❌ 错误示范

候选人原话 A:"ZGC 完全不停顿。"

问题诊断:ZGC 在 Root 扫描阶段仍然有 Stop-The-World,但 Root 扫描的时间与堆大小无关,只与 GC Roots 数量有关。

候选人原话 B:"ZGC 不需要 Remembered Set。"

问题诊断:ZGC 使用着色指针代替 Remembered Set,通过指针的颜色标记对象的 GC 状态,不需要维护 Region 间的引用关系。

1.3 标准回答

P5 级别:着色指针技术

ZGC 的染色指针(Colored Pointers)

ZGC 使用 64 位指针中的几位(42~45 位)作为颜色标记:

graph TD
    ZGC[64 位指针]
    ZGC --> B1[42-45 位<br/>Marked0 / Marked1<br/>Remapped<br/>Finalizable]
    ZGC --> B2[46-63 位<br/>堆地址]
    ZGC --> B3[0-41 位<br/>堆地址]

    style B1 fill:#ff6b6b

四种颜色

颜色含义
Marked0/Marked1对象是可达的
Remapped对象已移动到新地址(已重映射)
Finalizable对象只通过终结器引用可达

P6 级别:并发执行

ZGC 的并发阶段

ZGC 使用 读屏障(Load Barrier) 而非写屏障:

// 读屏障实现
Object obj = ref.read();  // 触发读屏障

// 读屏障检查指针颜色
if (obj.pointerColor == Marked0) {
    // 对象已标记
} else if (obj.pointerColor == Remapped) {
    // 对象已重映射(在新地址)
}

读屏障的开销

读屏障在每次读取对象引用时触发,但可以通过编译器优化(Barriers 折叠)将大部分读屏障的开销消除。

P7 级别:停顿时间 < 1ms 的原因

ZGC 停顿时间 < 1ms 的秘密

ZGC 的停顿时间与堆大小和存活对象数量无关,只与 GC Roots 数量有关

ZGC 停顿时间 = Root 扫描时间 + 指针更新时间
堆大小:4TB → 停顿时间仍 < 1ms

原因:ZGC 使用着色指针,GC 状态存储在指针上,不需要扫描整个堆来查找引用关系。

ZGC vs G1 的停顿时间对比

堆大小G1 停顿时间ZGC 停顿时间
4GB~200ms< 1ms
64GB~500ms< 1ms
1TBFull GC 可能 > 10s< 1ms

【面试官心理】 这道题我能问到 P7 级别,是因为 ZGC 的着色指针是 GC 技术的重大突破。能说清读屏障 vs 写屏障的候选人说明他理解了 ZGC 的核心创新。

1.4 追问升级

追问:ZGC 的着色指针和对象头中的 GC 信息有什么区别?

对象头中的 GC 信息需要维护 Remembered Set 来追踪跨 Region 引用。着色指针直接在指针上存储 GC 状态,通过读屏障验证,消除了 Remembered Set 的维护开销。

二、生产使用 🟢

2.1 ZGC 配置

# 启用 ZGC
-XX:+UseZGC

# 堆大小(ZGC 对大堆友好)
-Xmx64g -Xms64g

# 启用 NMT 监控
-XX:NativeMemoryTracking=summary

2.2 ZGC 的限制

  • ZGC 不支持类卸载(JDK 15+ 已支持)
  • ZGC 不支持压缩指针(JDK 15+ 已支持)
💡

面试加分点:能说出"JDK 21 的 ZGC 支持分代 ZGC(Generational ZGC),在原有 ZGC 的基础上引入了年轻代,进一步减少了 GC 频率和停顿时间",说明他关注了 JDK 新特性。

⚠️

面试陷阱:被问到"ZGC 为什么选择读屏障而不是写屏障",很多人会说"读屏障更快"。准确答案是:读屏障在 ZGC 中可以验证指针颜色,触发对象重映射(如果指针是旧地址的话)。写屏障虽然可以减少验证次数,但在 ZGC 的着色指针模型下,读屏障更适合。