zgc是java 11引入的低延迟垃圾收集器,目标是任意堆大小下停顿≤10ms,需避免高频临时对象分配、慎用finalizer/cleaner、减少跨代强引用,并通过日志、jmx及prometheus监控验证亚毫秒停顿。

ZGC(Z Garbage Collector)是 Java 11 引入的低延迟垃圾收集器,专为超大堆(TB 级)设计,目标是在任意堆大小下将 GC 停顿控制在 10ms 以内,实践中常稳定实现
确认运行环境与启用 ZGC
ZGC 要求 JDK 11+(推荐 JDK 17 或 21 LTS 版本),且仅支持 Linux/x64 和 Linux/AArch64 平台。Windows/macOS 上不可用。启用方式简洁,但必须显式关闭其他 GC:
- -XX:+UseZGC:核心开关,必须开启
- -Xms -Xmx 设为相同值(如 -Xms32g -Xmx32g):避免 ZGC 运行时动态扩展堆,否则可能触发额外同步停顿
- -XX:+UnlockExperimentalVMOptions(JDK 11–15 必须;JDK 16+ 已默认解锁)
示例启动命令:
java -Xms64g -Xmx64g -XX:+UseZGC -XX:+UnlockExperimentalVMOptions -jar app.jar合理设置并发线程数与内存页大小
ZGC 默认使用 CPU 核心数的 1/4 作为并发 GC 线程数(-XX:ConcGCThreads),但在超大堆(如 128G+)或高吞吐场景下,该值往往偏小,导致标记/转移滞后,增加单次停顿风险。建议手动调优:
- 物理 CPU 核数 ≥ 32 时,设为 -XX:ConcGCThreads=8~16
- 若机器内存带宽高(如 DDR5 + 多通道),可适度提高至 20,但不宜超过物理核数的 1/2
- -XX:+UseLargePages:启用透明大页(THP)或显式大页(HugePages),显著降低 TLB miss,对 64G+ 堆效果明显;需 OS 层配合配置(如 echo 1 > /proc/sys/vm/transparent_hugepage/enabled)
规避 ZGC 不友好的对象分配模式
ZGC 停顿虽短,但并非零开销。以下行为会放大其压力,间接导致 STW 时间上升或频率增加:
- 避免每秒创建 GB 级临时对象:ZGC 的并发标记依赖对象图遍历,过快的对象“出生-死亡”节奏会加重标记负担;可通过对象池(如 Netty 的 PooledByteBufAllocator)或复用结构体缓解
- 慎用 finalizer 或 Cleaner:ZGC 不处理 finalization 队列,这类对象会退化到 Full GC 流程,破坏低延迟承诺
- 减少跨代强引用:ZGC 是单代收集器(无年轻代/老年代划分),但若应用长期持有大量短生命周期对象的引用(如缓存未及时清理),会延长对象存活时间,增大并发标记工作量
监控与关键指标验证
仅看 GC 日志不够,需通过 JVM 内建指标验证是否真正达成亚毫秒停顿:
- 启用详细日志:-Xlog:gc*:stdout:time,uptime,level,tags(JDK 11+ 统一日志框架)
- 关注日志中 Pause Initiate Mark / Pause Final Mark / Pause Relocate 行,确认每次停顿 ≤ 0.8ms(典型亚毫秒表现)
- JMX 查看 jdk.management.gc.GarbageCollectorMXBean 中
getCollectionTime()和getCollectionCount(),计算平均停顿 = collectionTime / collectionCount;再结合getLastGcInfo().getDuration()看单次峰值 - 推荐接入 Prometheus + Grafana,采集
jdk.gc.ZStatisticsMBean 中的pause和mark子项,实时跟踪各阶段耗时分布
不复杂但容易忽略。ZGC 的亚毫秒能力不是“开箱即得”,而是堆规模、硬件、代码习惯和 JVM 参数共同作用的结果。重点不在堆越大越好,而在让 ZGC 的并发阶段跑得够快、够稳,把压力留在后台,而不是推给用户线程停顿。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











