Skip to content
JVM 与进程排障 · 第 2 篇 / 共 3 篇
领域编程与框架
专题Java 专题
当前序列JVM 与进程排障
阅读位置第 2 篇 / 共 3 篇当前专题第 5 个序列 / 共 10 个序列

GC 日志怎么看:先看频率、停顿时间,再看是不是 Young GC 和 Full GC

很多人第一次看 GC 日志,会直接被一大串时间、分区和内存数字劝退。

其实真正排查线上问题时,不需要一上来就做 JVM 调优专家。先把最重要的几个判断做对,已经能解决很多问题。

先说结论

看 GC 日志时,优先回答四个问题:

  1. GC 发生得频不频繁
  2. 停顿时间长不长
  3. 是 Young GC 多,还是 Full GC 多
  4. GC 之后内存有没有明显回落

这四件事比单纯盯着某一行日志更重要。

一、先把两类 GC 分清楚

Young GC

主要回收新生代。

一般特点:

  • 次数相对更多
  • 单次停顿通常更短

Full GC

会涉及老年代,通常代价更大。

如果线上频繁出现 Full GC,通常就要提高警惕了。

它可能意味着:

  • 老年代对象堆积严重
  • 内存泄漏
  • 大对象分配异常
  • 晋升压力过大

二、GC 日志最值得先看什么

1. 频率

如果 GC 非常频繁,即使每次停顿不长,也可能明显影响吞吐。

2. 停顿时间

如果单次停顿很长,用户侧更容易直接感知到卡顿。

3. 回收前后内存变化

例如:

  • GC 前使用量很高
  • GC 后却几乎没降多少

这往往说明:

  • 活对象很多
  • 或者存在无法释放的引用

三、先给出一套够用的阅读顺序

可以按这个顺序看:

  1. 先看是否频繁出现 Full GC
  2. 再看每次停顿是否明显变长
  3. 看 GC 后堆是否能降回合理区间
  4. 如果降不回去,再结合 Heap Dump、MAT、对象分布继续查

四、GC 日志常见的几种信号

1. Young GC 很多,但 Full GC 很少

这不一定是问题。

如果:

  • 停顿可接受
  • 服务吞吐正常

那只是正常回收行为。

2. Full GC 开始频繁出现

这是更值得优先关注的信号。

要继续排查:

  • 老年代是不是一直涨
  • 是否有缓存、集合、ThreadLocal 等对象留住内存

3. GC 后内存回不去

这通常比“GC 频繁”更值得警惕。

因为它更像:

  • 活对象真实很多
  • 或者存在泄漏

4. 停顿时间越来越长

这可能意味着:

  • 堆太大但对象结构复杂
  • Full GC 成本高
  • 内存碎片或晋升压力明显

五、日志之外还要配合看什么

GC 日志不是孤立看的。

通常还要结合:

  • 应用响应时间
  • CPU 使用率
  • 堆使用趋势
  • jstat
  • Heap Dump

如果只是盯日志文本,很容易只看到表象。

六、JDK 版本不同,日志参数也不同

JDK 8 常见写法

bash
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/path/gc.log

JDK 9+ 常见写法

bash
-Xlog:gc*:file=/path/gc.log:time,uptime,level,tags

如果你现在是新项目,优先按 JDK 9+ 的方式理解更合适。

七、一个更贴近排障现场的判断方式

可以这样简单分层:

应用偶尔卡顿

先看:

  • 是否存在长时间停顿的 Full GC

内存一直涨

先看:

  • GC 后内存是否回落

吞吐明显下降

先看:

  • GC 频率是否异常高
  • 应用线程是否大量时间都花在 GC 停顿外等待资源

八、不要一上来就调参数

很多 JVM 问题,最后根因并不是“参数不够好”,而是:

  • 集合无限增长
  • 缓存没有上限
  • 临时对象产生过多
  • 大对象处理方式不合理

所以更稳妥的顺序通常是:

  1. 先确认是不是代码层对象问题
  2. 再考虑 JVM 参数和 GC 策略优化

一句话总结

GC 日志最重要的不是逐行背格式,而是先看:

  • 频率
  • 停顿
  • Full GC
  • 回收后是否降得下来

把这四件事看明白,GC 日志就已经不再难读了。

延伸阅读相关文章优先当前专题,再补跨专题关联。
同一序列 · 顺着当前主线继续读Java 进程排查与 Heap Dump 使用记录适合把 GC、内存分析和 Java 进程排查放在同一条诊断主线上看。Java 专题 · JVM 与进程排障同一序列 · 回看前文会更完整JVM 内存问题怎么分析适合把 GC、内存分析和 Java 进程排查放在同一条诊断主线上看。Java 专题 · JVM 与进程排障同专题其他序列 · Java 类加载与运行时细节对象是在堆上分配还是在栈上逃逸适合把类加载、双亲委派和运行时对象分配放到一起系统看。Java 专题 · Java 类加载与运行时细节同专题其他序列 · Java 类加载与运行时细节双亲委派模型到底解决了什么适合把类加载、双亲委派和运行时对象分配放到一起系统看。Java 专题 · Java 类加载与运行时细节跨专题关联 · 同场景:基础学习@Conditional 系列注解怎么配合使用适合把自动装配、条件装配、Profile 和循环依赖放回 Spring Boot 启动过程里理解。Spring 专题 · Spring Boot 启动、装配与配置跨专题关联 · 同场景:基础学习保留策略和日志压缩适合哪些场景适合把副本机制、acks、批量压缩和日志组织放在一条 Kafka 投递主线上理解。Kafka 专题 · Kafka 投递链路与日志存储机制
继续阅读JVM 与进程排障当前序列第 2 篇 / 共 3 篇当前专题第 5 个序列 / 共 10 个序列
往前看
上一篇JVM 内存问题怎么分析回到当前序列上一章上一序列Java 线程池与异步编排从第 1 篇开始:线程池参数怎么配
往后看
下一篇Java 进程排查与 Heap Dump 使用记录继续当前序列下一章下一序列Java 锁实现与并发细节从第 1 篇开始:synchronized 为什么仍然是 Java 并发里的默认首选

把零散经验整理成可查、可复用、可持续更新的企业级知识门户