ZGC 收集器原理
候选人小陈在面试字节 P7 时,面试官问道:
"ZGC 的核心设计是什么?"
小陈说:"ZGC 使用着色指针..."面试官追问:"着色指针是怎么工作的?"
小陈答不上来。面试官继续追问:"ZGC 为什么能做到 < 1ms 的停顿?"
小陈彻底卡住了...
一、核心问题:ZGC 收集器原理 🔴
1.1 问题拆解
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 位)作为颜色标记:
四种颜色:
P6 级别:并发执行
ZGC 的并发阶段:
ZGC 使用 读屏障(Load Barrier) 而非写屏障:
读屏障的开销:
读屏障在每次读取对象引用时触发,但可以通过编译器优化(Barriers 折叠)将大部分读屏障的开销消除。
P7 级别:停顿时间 < 1ms 的原因
ZGC 停顿时间 < 1ms 的秘密:
ZGC 的停顿时间与堆大小和存活对象数量无关,只与 GC Roots 数量有关。
原因:ZGC 使用着色指针,GC 状态存储在指针上,不需要扫描整个堆来查找引用关系。
ZGC vs G1 的停顿时间对比:
【面试官心理】 这道题我能问到 P7 级别,是因为 ZGC 的着色指针是 GC 技术的重大突破。能说清读屏障 vs 写屏障的候选人说明他理解了 ZGC 的核心创新。
1.4 追问升级
追问:ZGC 的着色指针和对象头中的 GC 信息有什么区别?
对象头中的 GC 信息需要维护 Remembered Set 来追踪跨 Region 引用。着色指针直接在指针上存储 GC 状态,通过读屏障验证,消除了 Remembered Set 的维护开销。
二、生产使用 🟢
2.1 ZGC 配置
2.2 ZGC 的限制
- ZGC 不支持类卸载(JDK 15+ 已支持)
- ZGC 不支持压缩指针(JDK 15+ 已支持)
面试加分点:能说出"JDK 21 的 ZGC 支持分代 ZGC(Generational ZGC),在原有 ZGC 的基础上引入了年轻代,进一步减少了 GC 频率和停顿时间",说明他关注了 JDK 新特性。
面试陷阱:被问到"ZGC 为什么选择读屏障而不是写屏障",很多人会说"读屏障更快"。准确答案是:读屏障在 ZGC 中可以验证指针颜色,触发对象重映射(如果指针是旧地址的话)。写屏障虽然可以减少验证次数,但在 ZGC 的着色指针模型下,读屏障更适合。