欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > ZGC 参数优化与 GC 触发机制解析分享

ZGC 参数优化与 GC 触发机制解析分享

2025/4/3 6:16:51 来源:https://blog.csdn.net/xiaofeng10330111/article/details/146117856  浏览:    关键词:ZGC 参数优化与 GC 触发机制解析分享

目录

一、ZGC 重要配置参数解析

(一) ZGC 关键参数配置

(二)基本配置前置说明

二、 ZGC 触发时机分析

(一)ZGC 触发机制分类

(二)ZGC 触发机制的基础优化建议

(三)关键日志示例

三、理解和分析 ZGC 日志

(一)ZGC 日志结构解析

(二)关键日志示例

1. 关注核心点标注

2. 日志解析说明

(三)如何利用日志进行调优?

四、理解 ZGC 停顿原因

(一)ZGC 停顿原因分类

(二)详细解析各类停顿

1. GC 过程中 STW 相关停顿

🔹 初始标记(Pause Mark Start)

🔹 再标记(Pause Mark End)

🔹 初始转移(Pause Relocate Start)

2. 非 GC 触发的停顿

🔹 内存分配阻塞(Allocation Stall)

🔹 安全点(Safepoint)

🔹 线程 / 内存 Dump(jstack / jmap)

(三)如何分析 ZGC 停顿日志?

1. 关键排查步骤

2. 整体关注方向

五、总结


干货分享,感谢您的阅读!

在 Java 应用的高并发和低延迟场景下,垃圾回收(GC)机制的优化至关重要。ZGC 作为现代 JVM 提供的一款低延迟垃圾回收器,以其并发回收、高吞吐的特性受到广泛关注。然而,想要真正发挥 ZGC 的优势,合理的参数配置、触发机制优化以及日志分析都是不可或缺的环节。本篇文章深入解析了 ZGC 的关键参数、触发时机、日志分析以及可能的 STW 停顿原因,并提供了具体的优化策略,帮助开发者更高效地利用 ZGC,提升 Java 应用的稳定性和性能。

 历史主要基本文章回顾:

涉猎内容具体链接
Java GC 基础知识快速回顾Java GC 基础知识快速回顾-CSDN博客
垃圾回收基本知识内容Java回收垃圾的基本过程与常用算法_java垃圾回收过程-CSDN博客
CMS调优和案例分析CMS垃圾回收器介绍与优化分析案列整理总结_cms 对老年代的回收做了哪些优化设计-CSDN博客
G1调优分析Java Hotspot G1 GC的理解总结_java g1-CSDN博客
ZGC基础和调优案例分析垃圾回收器ZGC应用分析总结-CSDN博客

从ES的JVM配置起步思考JVM常见参数优化

从ES的JVM配置起步思考JVM常见参数优化_es jvm配置-CSDN博客

深入剖析GC问题:如何有效判断与排查

深入剖析GC问题:如何有效判断与排查_排查java堆中大对象触发gc-CSDN博客

动态扩缩容引发的JVM堆内存震荡调优指南

动态扩缩容引发的JVM堆内存震荡:从原理到实践的GC调优指南

显式 GC 的使用:留与去,如何选择?

显式 GC 的使用:留与去,如何选择?

堆外内存 OOM:现象分析与优化方案

堆外内存 OOM:现象分析与优化方案

过早晋升的识别与优化实战

Java垃圾回收的隐性杀手:过早晋升的识别与优化实战

如何选取合适的 NewRatio 值

如何选取合适的 NewRatio 值来优化 JVM 的垃圾回收策略

解决 CMS Old GC 频繁触发

解决 CMS Old GC 频繁触发优化 Java 性能的技术方案

降低请求高峰期GC Remark阶段停顿时间

CMS GC优化实战:降低请求高峰期GC Remark阶段停顿时间

避免 CMS GC退化操作

分析CMS GC退化为单线程串行GC模式的原因与优化

解决单次 CMS Old GC 耗时长问题

单次 CMS Old GC 耗时长问题分析与优化

高效解决MetaSpace OOM 问题

深入剖析 MetaSpace OOM 问题:根因分析与高效解决策略

减少 Minor GC 频率,优化系统吞吐

深入解析 Java GC 调优:减少 Minor GC 频率,优化系统吞吐
高频面试题汇总JVM高频基本面试问题整理_jvm面试题-CSDN博客

一、ZGC 重要配置参数解析

在现代 Java 应用中,ZGC(Z Garbage Collector) 以其低延迟、高吞吐的特性广受欢迎。然而,要充分发挥 ZGC 的优势,合理的参数配置至关重要。

(一) ZGC 关键参数配置

参数作用默认值示例值优化建议
-Xms / -Xmx设置 JVM 堆的最小 / 最大大小物理内存的 1/4-Xms10G -Xmx10G设为相同值,避免堆扩展影响性能
-XX:ReservedCodeCacheSizeJIT 代码缓存区最大大小240MB-XX:ReservedCodeCacheSize=256m适用于 JIT 代码多的应用
-XX:InitialCodeCacheSizeJIT 代码缓存区初始大小240MB-XX:InitialCodeCacheSize=256m预留足够空间减少扩容开销
-XX:+UnlockExperimentalVMOptions解锁实验性 JVM 选项关闭-XX:+UnlockExperimentalVMOptions必须启用,才能使用 ZGC
-XX:+UseZGC启用 ZGC 作为垃圾回收器关闭-XX:+UseZGC适用于低延迟场景
-XX:ConcGCThreads并发 GC 线程数CPU 核心数的 12.5%-XX:ConcGCThreads=2适当增大,提高回收速度
-XX:ParallelGCThreadsSTW GC 线程数CPU 核心数的 60%-XX:ParallelGCThreads=6适当增加,缩短 STW 时间
-XX:ZCollectionIntervalZGC 最小回收间隔(秒)10s-XX:ZCollectionInterval=120减少频繁回收,降低 GC 开销
-XX:ZAllocationSpikeTolerance自适应触发 ZGC 的灵敏度2-XX:ZAllocationSpikeTolerance=5适用于突发内存分配场景
-XX:+UnlockDiagnosticVMOptions解锁 JVM 诊断选项关闭-XX:+UnlockDiagnosticVMOptions便于调试 GC 行为
-XX:-ZProactive是否启用 ZGC 主动回收开启-XX:-ZProactive关闭主动回收,减少额外 CPU 开销
-Xlog配置 GC 日志默认 minimal 级别-Xlog:safepoint,gc*=info:file=/opt/logs/gc-%t.log:time,tid,tags:filecount=5,filesize=50m便于排查 GC 问题

(二)基本配置前置说明

  • 固定堆大小-Xms = -Xmx),避免扩容带来的 GC 开销。
  • 调整 GC 线程,适量增加 -XX:ConcGCThreads-XX:ParallelGCThreads 以优化吞吐量。
  • 合理的 ZGC 触发策略-XX:ZCollectionInterval-XX:ZAllocationSpikeTolerance),平衡回收频率和延迟。
  • 开启 GC 日志-Xlog),便于监控和优化 GC 行为。

以上配置说明只是基本说明,具体需要在项目上线前进行严格的校对,整体目标:有效提升 ZGC 性能,减少 应用停顿时间,适用于 低延迟高吞吐 的 Java 应用场景。

二、 ZGC 触发时机分析

相比于 CMSG1 的 GC 触发机制,ZGC 采用并发回收,在 GC 过程中仍然允许对象分配。其 核心挑战 在于如何确保 GC 完成前,新分配的对象不会将堆占满,否则会导致 线程停顿,影响应用性能。

(一)ZGC 触发机制分类

触发机制触发条件适用场景关键日志关键字优化参数
阻塞内存分配请求触发当垃圾未及时回收,导致堆被填满时,部分线程会因无法分配内存而阻塞应避免,否则可能导致应用长时间 STWAllocation Stall需通过 其他触发机制 避免
基于分配速率的自适应触发结合 近期分配速率GC 耗时 计算内存阈值,超过则触发 GC主要触发方式,适用于 大部分场景Allocation Rate-XX:ZAllocationSpikeTolerance (默认 2,越大越早触发)
基于固定时间间隔触发每隔一定时间(秒)触发 GC适合流量突增场景(如秒杀、定时任务)Timer-XX:ZCollectionInterval=120
主动触发规则ZGC 自行计算 触发时机,时间间隔 非固定适用于默认场景,但可能导致 频繁 GCProactive-XX:-ZProactive 可关闭
预热规则服务 刚启动 时触发仅在应用启动阶段出现,一般不需要调整Warmup无需优化
外部触发代码中 显式调用 System.gc()人为触发 GC,应 谨慎使用System.gc()避免手动 System.gc()
元数据分配触发元数据区不足 时触发较少出现,一般不影响业务Metadata GC Threshold无需优化

(二)ZGC 触发机制的基础优化建议

  • 避免 Allocation Stall 触发:一旦日志出现 Allocation Stall,说明 GC 来不及回收,需 调整 ZGC 触发时机,比如:
    • 增大 -XX:ConcGCThreads,提升并发回收能力
    • 降低 -XX:ZAllocationSpikeTolerance,让 ZGC 更早触发
    • 减少 -XX:ZCollectionInterval,提高 GC 触发频率
  • 针对流量突增场景,建议开启 固定时间间隔触发-XX:ZCollectionInterval),防止 GC 触发过晚,导致瞬间负载过高。
  • 主动触发 vs. 固定间隔触发:如果已经开启 固定时间间隔 GC,可以 关闭 -XX:-ZProactive,避免额外 GC 影响吞吐量。

(三)关键日志示例

可通过 -Xlog:gc* 观察 ZGC 触发情况,示例如下:

[2025-03-08T12:34:56.789+0000][info][gc] GC(42) Pause (Allocation Stall) 2.345ms 
[2025-03-08T12:35:01.123+0000][info][gc] GC(43) Concurrent Cycle 456ms 
[2025-03-08T12:36:00.567+0000][info][gc] GC(44) Pause (Proactive) 1.678ms
  • Allocation Stall:表明 ZGC 触发过晚,需优化触发策略
  • Concurrent Cycle:表示正常的 ZGC 回收周期
  • Proactive:主动 GC 触发,若不需要可通过 -XX:-ZProactive 关闭

上面只是简单的示例,我们后续会详解这部分。ZGC 触发机制的调优关键在于 提前回收垃圾,避免线程阻塞。理解 各类触发条件结合日志分析,可以有效优化 ZGC,确保应用在高并发场景下的 低延迟、无卡顿运行

三、理解和分析 ZGC 日志

ZGC 运行时会生成详细的 GC 日志,分析日志可以帮助我们理解 GC 触发原因、回收过程以及堆内存变化。在一次完整的 GC 过程中,日志包含多个阶段,其中部分阶段涉及 Stop-The-World(STW)

(一)ZGC 日志结构解析

日志项说明是否 STW
StartGC 开始,包含 触发原因(如 Allocation RateTimer 等)
Phase-Pause Mark Start初始标记 阶段,标记存活对象
Phase-Pause Mark End再次标记 阶段,确保存活对象不被错误回收
Phase-Pause Relocate Start转移阶段,ZGC 采用 Region 级别的对象移动
Heap 信息记录 GC 过程中 MarkRelocate 前后的堆内存使用情况
GC 信息统计统计 10 秒、10 分钟、10 小时 内的 GC 数据,帮助长期优化

(二)关键日志示例

1. 关注核心点标注

日志中内容较多,关键点已用红线标出,含义较好理解,详细解释可官网OpenJDK: ZGC查阅资料:

2. 日志解析说明

以下是 GC 日志示例(省略部分内容):

[2025-03-08T12:34:56.123+0000][info][gc] GC(42) Start (Allocation Rate)
[2025-03-08T12:34:56.125+0000][info][gc] GC(42) Phase-Pause Mark Start 2.5ms
[2025-03-08T12:34:56.130+0000][info][gc] GC(42) Phase-Pause Mark End 3.1ms
[2025-03-08T12:34:56.135+0000][info][gc] GC(42) Phase-Pause Relocate Start 1.2ms
[2025-03-08T12:34:56.150+0000][info][gc] GC(42) Heap before GC: High 8.5GB, Low 7.2GB
[2025-03-08T12:34:56.155+0000][info][gc] GC(42) Heap after GC: High 4.2GB, Low 3.1GB
[2025-03-08T12:34:56.200+0000][info][gc] GC(42) GC Info: Last 10s - 4 GCs, Last 10m - 24 GCs
  • GC 触发原因Start (Allocation Rate) 说明 由于分配速率过高,ZGC 自动触发 GC
  • STW 阶段Mark StartMark EndRelocate Start 都是 STW 阶段,需关注时间是否过长。
  • 堆变化
    • GC 前:堆占用 High 8.5GB,Low 7.2GB
    • GC 后:堆占用降至 High 4.2GB,Low 3.1GB,说明本次 GC 释放了大量内存。
  • 长期 GC 统计:最近 10 秒内触发 4 次 GC,最近 10 分钟触发 24 次 GC,说明 GC 频率较高,可能影响吞吐量。

(三)如何利用日志进行调优?

日志项潜在问题优化建议
Allocation Stall 频繁出现GC 触发过晚,导致线程因分配失败阻塞调小 -XX:ZAllocationSpikeTolerance,加快 GC 触发
Phase-Pause Mark Start 耗时较长STW 过长,影响延迟增加 -XX:ConcGCThreads,加快并发标记
Heap High Used ≈ 100%内存不足,可能影响吞吐增加 -Xmx,或优化对象分配策略
GC Info 统计中 短时间 GC 过于频繁GC 过度触发,可能影响吞吐量适当增大 -XX:ZCollectionInterval,降低 GC 频率

ZGC 日志提供了 GC 触发原因、堆使用情况、STW 时间、长期 GC 统计 等关键信息。结合日志分析,可以有效优化 GC 触发时机、吞吐量、内存占用,确保应用在 低延迟、高并发场景 下稳定运行。

四、理解 ZGC 停顿原因

ZGC 以 低延迟(Low Latency)并发回收(Concurrent GC) 为核心设计目标,尽量减少 Stop-The-World(STW) 时间,但仍然存在某些不可避免的停顿场景。根据实战经验,我们总结了 六种导致程序停顿的原因,并结合官方文档进行详细解析。

(一)ZGC 停顿原因分类

停顿类型日志关键字STW 时长影响触发原因
初始标记(Pause Mark Start)Phase-Pause Mark Start短暂GC 启动时,STW 以标记根对象
再标记(Pause Mark End)Phase-Pause Mark End短暂标记过程中存活对象的调整
初始转移(Pause Relocate Start)Phase-Pause Relocate Start短暂为对象迁移做好准备
内存分配阻塞(Allocation Stall)Allocation Stall可能较长堆已满,等待 GC 完成
安全点停顿(Safepoint)VM Operation (safepoint)可能较长线程挂起以进入 GC
线程 / 内存 Dump(Dump Threads / Heap)jstack / jmap取决于 Dump 规模手动执行 jstack、jmap 等工具

(二)详细解析各类停顿

1. GC 过程中 STW 相关停顿

ZGC 采用 并发回收,但部分阶段仍需 STW。以下 STW 事件通常较短,不是性能瓶颈,但仍需关注。

🔹 初始标记(Pause Mark Start)
  • 日志示例
    [2025-03-08T12:34:56.123+0000][info][gc] GC(42) Pause Mark Start 2.5ms
  • 作用
    • ZGC 的 GC 采用 染色指针(Colored Pointers) 技术,但仍需 STW 扫描 GC Roots(线程栈、全局变量等)。
    • 由于根对象数量通常较少,这个阶段的 STW 时间通常低于 10ms
  • 优化建议
    • -XX:ConcGCThreads=N(调整并发标记线程数)
    • -Xms-Xmx 设为相同值,避免动态扩缩容影响 GC
🔹 再标记(Pause Mark End)
  • 日志示例
    [2025-03-08T12:34:56.130+0000][info][gc] GC(42) Pause Mark End 3.1ms
  • 作用
    • 由于 ZGC 并发标记时仍允许对象分配,再标记阶段确保存活对象不会被误回收。
    • 这个阶段一般 比初始标记稍长,但通常不会超过 10ms。
  • 优化建议:适当增大 -XX:ParallelGCThreads,减少 STW 时间。
🔹 初始转移(Pause Relocate Start)
  • 日志示例
    [2025-03-08T12:34:56.135+0000][info][gc] GC(42) Pause Relocate Start 1.2ms
  • 作用
    • ZGC 采用 Region 级别的对象迁移(Relocation),此阶段主要做准备工作。
    • STW 时长一般 远小于 Mark 阶段,通常 小于 5ms

2. 非 GC 触发的停顿

🔹 内存分配阻塞(Allocation Stall)
  • 日志示例
    [2025-03-08T12:34:56.150+0000][warning][gc] Allocation Stall (Heap is Full)
  • 触发条件:ZGC 采用 并发回收,但如果分配速率过高,GC 来不及清理内存,就会导致线程因等待 GC 而阻塞。
  • 优化建议
    • 减少 Allocation Stall
      • 调整 -XX:ZAllocationSpikeTolerance,默认值 2,值越大越早触发 GC。
      • 增大 -Xmx,预留足够堆空间。
    • 监控 Allocation Rate 关键日志GC(42) Allocation Rate 200MB/s → 如果过高,GC 可能来不及回收。
🔹 安全点(Safepoint)
  • 日志示例
    [2025-03-08T12:34:56.200+0000][info][safepoint] VM Operation (safepoint) 10ms
  • 作用
    • ZGC 需要 所有线程进入安全点 才能执行 GC,先进入安全点的线程需等待 所有线程 进入。
    • 线程阻塞的时间取决于 最慢的线程
  • 优化建议
    • 避免过多 长时间运行的 Native 方法(会阻塞安全点)。
    • 使用 -XX:+UseLargePages 以减少安全点同步的开销。
🔹 线程 / 内存 Dump(jstack / jmap)
  • 日志示例
    [2025-03-08T12:34:56.300+0000][info][heap] Heap Dump initiated by jmap
  • 触发条件:执行 jstackjmapjcmd 可能会引发 STW 停顿,取决于 Dump 规模。
  • 优化建议生产环境避免频繁 Dump,可使用 Async-profilerperf 进行低开销分析。这里如果有公司级的手段就直接使用,以笔者工作过的美团和支付宝为例,内部的工具整体上已经够用了。

(三)如何分析 ZGC 停顿日志?

1. 关键排查步骤

  • 检查 Allocation Stall 是否出现:如频繁发生,调整 -XX:ZAllocationSpikeTolerance
  • 关注 Pause Mark Start / Pause Mark End 耗时:STW 超过 10ms,考虑增大 -XX:ConcGCThreads
  • 监控 Safepoint 耗时:若时间过长,检查是否有 长时间运行的 Native 方法
  • 分析 Heap Dump 触发原因:避免频繁 jmap,可用 -XX:+HeapDumpOnOutOfMemoryError 在 OOM 时自动 Dump。

2. 整体关注方向

  • ZGC 的 STW 停顿通常较短,但 内存分配阻塞 可能会导致较长停顿,应重点优化 ZAllocationSpikeToleranceXmx 配置。
  • 安全点(Safepoint) 可能会影响 STW,避免 长时间运行的 Native 方法
  • Heap Dump 和 jstack 操作 可能引发 STW,应 减少在线环境频繁使用
  • 定期分析 GC 日志,监控 Allocation RateHeap Used,避免分配速率过高导致 GC 触发延迟。

ZGC 虽然减少了 STW,但并非完全无停顿,合理的参数优化仍然是提升性能的关键! 🚀

五、总结

ZGC 作为一款低延迟 GC,适用于高吞吐、低停顿的 Java 应用场景。通过合理配置参数、优化触发机制以及深入分析 GC 日志,可以有效降低 GC 对应用性能的影响。本文详细解析了 ZGC 的核心参数、触发原理、关键日志以及常见的停顿问题,并提供了针对性的优化建议。希望这些内容能够帮助开发者更好地理解和调优 ZGC,使 Java 应用在复杂业务环境下依然能保持高效、稳定运行。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词