JVM GC 日志分析实战指南——别再只看 Full GC 次数了 JVM GC 日志分析实战指南——别再只看 Full GC 次数了一、GC 问题要看上下文JVM 排障时Full GC 次数很显眼但只看次数不够。一次 Full GC 可能是正常元数据回收也可能是堆压力失控年轻代 GC 频繁也可能已经严重影响延迟。GC 日志分析要看暂停时间、回收效果、分配速率和业务延迟。GC 不是越少越好而是要和服务目标匹配。二、先打开可用日志flowchart TD A[JVM 运行] -- B[GC 日志] B -- C[暂停时间] B -- D[堆变化] B -- E[原因] C -- F[性能判断]JDK 11 之后可以使用统一日志参数。-Xlog:gc*:filegc.log:time,uptime,level,tags日志要和应用版本、实例、时间窗口关联否则事后很难对应业务现象。三、看回收前后变化Pause Young (Normal) 512M-180M(1024M) 35ms这类日志要看三个点暂停类型、回收前后堆大小、暂停时间。年轻代回收后剩余很多可能对象晋升压力大Full GC 后仍释放不出空间可能有内存泄漏或缓存失控。还要看分配速率。如果业务突然创建大量短生命周期对象Minor GC 会变频繁。优化方向可能是减少临时对象而不是盲目加堆。四、GC 要和业务指标对齐GC 日志单独看很容易误判。要把暂停时间和接口 P99、线程池队列、CPU 使用率放在同一时间线上。gc_analysis_context: p99_latency: true allocation_rate: true old_gen_usage: true thread_pool_queue: true如果 GC 暂停和接口抖动时间一致才有更强证据。否则接口慢可能是下游、锁或网络。不同 GC 器关注点也不同。G1 要看 region、mixed GC、humongous objectZGC/Shenandoah 更关注并发阶段和极低暂停目标。不要用一套经验判断所有 GC。最后调参前先确认目标。是降低 P99减少 CPU还是降低内存成本目标不同参数选择也不同。GC 分析还要关注对象来源。只知道分配速率高不够要进一步看哪些类在分配。可以结合 JFR、async-profiler 或堆采样工具找到热点对象。jcmd pid JFR.start namegc-profile settingsprofile duration120s filenamegc.jfr如果热点来自日志拼接、JSON 序列化、临时集合、重复对象转换优化代码可能比调 JVM 参数更有效。还要关注大对象。G1 里的 humongous object 会带来特殊压力大 byte array、大字符串、大 JSON 都可能触发问题。看到堆还有空间但 GC 抖动也要检查大对象分配。最后GC 优化要做对比实验。改堆大小、换 GC、调 region不要一次改一堆。每次只改一个变量观察 P95/P99、CPU、吞吐和内存成本。GC 日志也要保存足够周期。很多问题只在高峰、批任务或特定租户流量下出现如果日志很快被覆盖就无法回看。生产环境可以压缩归档 GC 日志并在告警触发时保留现场。gc_log_retention: keep_days: 7 archive_on_alert: true attach_to_incident: true还要注意容器内存限制。JVM 看到的可用内存、容器 limit 和实际节点压力如果不一致GC 判断会偏。排查容器化 Java 服务时必须同时看 JVM 参数和 cgroup 限制。GC 参数调优也有 Trade-offs。降低暂停时间通常意味着更频繁的 GC 周期和更高的 CPU 开销增大堆可以减少 GC 频率但会增加单次暂停时间和内存成本。在容器化环境中还要考虑节点上其他容器的内存压力。一个实用的做法是先确定服务的 SLO如 P99 延迟不超过 500ms再反过来推导可接受的 GC 暂停上限而不是一味追求最少 GC 次数。对于延迟敏感服务G1 的MaxGCPauseMillis设置要保守避免系统为了追求低暂停而频繁并发标记反而增加 CPU 消耗。GC 日志分析工具的选型也值得关注。开源工具如 GCViewer、GCeasy 适合快速概览但在处理超大日志文件如几天的高频 GC 日志时可能性能不足。对于关键服务建议在构建 pipeline 里集成自动 GC 分析每次发布后对比 GC 行为变化而不是等线上出问题才看日志。可以设置简单的阈值告警如年轻代 GC 频率比上周增加 30%或Full GC 后老年代回收比例低于 20%这些是内存泄漏或堆设置不合理的早期信号。五、总结JVM GC 日志分析要看暂停类型、暂停时间、回收效果、分配速率、GC 原因和业务延迟关联。别只看 Full GC 次数。GC 排障要回答的是它有没有破坏服务目标以及为什么。