如何通过jstat -gccause命令实时查看触发垃圾回收的具体原因?

2026-04-30 17:001阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计959个文字,预计阅读时间需要4分钟。

如何通过jstat -gccause命令实时查看触发垃圾回收的具体原因?

由于使用 `jstat -gc` 只会告诉你 发生了GC,而 `jstat -gccause` 会明确告诉你 为什么现在发生了GC。例如,看到 `Metadata GC Threshold`,你就知道是 Metaspace 快满了,而不是代码写错、内存泄漏,或者是类加载太多或未及时卸载。这个区别直接决定了你是否需要调整参数、检查类加载器,甚至可能需要升级 Spring Boot 的 auto-configuration。

jstat -gccause 的输出列怎么看

它和 jstat -gc 输出结构一致,但多出两列:LGCC(Last GC Cause)和 CGCC(Current GC Cause)。注意:这两列是字符串,不是数字。

  • LGCC:上一次 GC 是被什么触发的,例如 Allocation Failure(Eden 满)、Metadata GC Threshold(Metaspace 达限)、System.gc()(有人手动调了)
  • CGCC:当前采样时刻,**正在发生的 GC 是由什么触发的**。如果这一列是 No GC,说明此刻没在 GC;如果是 Metadata GC Threshold,那说明 JVM 正因 Metaspace 不足而准备或正在进行 GC
  • 常见值还有:G1 Evacuation Pause(G1 在做年轻代回收)、Allocation Profiling(ZGC 启用了分配采样)、Full GC(老年代真的撑不住了)

怎么用才不漏掉关键触发点

单次执行容易错过瞬时 GC,必须加时间间隔和次数,否则可能只看到 No GC 就以为没事——实际 GC 可能每 200ms 触发一次,你 1 秒采一次根本抓不到。

  • 推荐命令:jstat -gccause <pid> 200 50(每 200ms 采一次,共 50 次,覆盖 10 秒窗口)
  • 重点盯 CGCC 列连续出现的非 No GC 值,比如反复出现 Metadata GC Threshold,说明 Metaspace 长期处于临界状态
  • 别只看最后一行——GC 原因可能在第 3 行就首次暴露,后面几行只是重复;要扫完整输出,尤其关注第一次非 No GC 出现的位置
  • 如果 CGCCSystem.gc(),立刻检查代码里有没有 System.gc() 或启用了 -XX:+ExplicitGCInvokesConcurrent

看到 Metadata GC Threshold 后该做什么

这不是警告,是已发生的事实:JVM 已经因为 Metaspace 不足触发了 GC,且大概率失败了(否则不会继续报这个原因),接下来可能频繁 Full GC 或 OOM。

  • 先确认 Metaspace 当前配置:jinfo -flag MaxMetaspaceSize <pid>,如果输出 -XX:MaxMetaspaceSize=-1(即不限制),反而更危险——它会不断扩容直到耗尽本地内存
  • 对比 MC(Metaspace 容量)和 MU(已使用):如果 MU / MC > 0.95,基本就是瓶颈
  • 临时缓解可加:-XX:MaxMetaspaceSize=256m -XX:MetaspaceSize=128m(设初始值避免频繁扩容)
  • 根因排查得结合 jmap -clstats <pid> 看类加载器数量,或用 jcmd <pid> VM.native_memory summary 查 native 内存是否被 class metadata 占满

真正容易被忽略的是:Metaspace GC 不会释放所有元数据,只有**无引用的类加载器及其加载的类**才会被卸载。所以即使调大 MaxMetaspaceSize,如果存在 ClassLoader 泄漏(如 ThreadLocal 持有、OSGi、热部署框架残留),问题只会延后爆发。

标签:JS

本文共计959个文字,预计阅读时间需要4分钟。

如何通过jstat -gccause命令实时查看触发垃圾回收的具体原因?

由于使用 `jstat -gc` 只会告诉你 发生了GC,而 `jstat -gccause` 会明确告诉你 为什么现在发生了GC。例如,看到 `Metadata GC Threshold`,你就知道是 Metaspace 快满了,而不是代码写错、内存泄漏,或者是类加载太多或未及时卸载。这个区别直接决定了你是否需要调整参数、检查类加载器,甚至可能需要升级 Spring Boot 的 auto-configuration。

jstat -gccause 的输出列怎么看

它和 jstat -gc 输出结构一致,但多出两列:LGCC(Last GC Cause)和 CGCC(Current GC Cause)。注意:这两列是字符串,不是数字。

  • LGCC:上一次 GC 是被什么触发的,例如 Allocation Failure(Eden 满)、Metadata GC Threshold(Metaspace 达限)、System.gc()(有人手动调了)
  • CGCC:当前采样时刻,**正在发生的 GC 是由什么触发的**。如果这一列是 No GC,说明此刻没在 GC;如果是 Metadata GC Threshold,那说明 JVM 正因 Metaspace 不足而准备或正在进行 GC
  • 常见值还有:G1 Evacuation Pause(G1 在做年轻代回收)、Allocation Profiling(ZGC 启用了分配采样)、Full GC(老年代真的撑不住了)

怎么用才不漏掉关键触发点

单次执行容易错过瞬时 GC,必须加时间间隔和次数,否则可能只看到 No GC 就以为没事——实际 GC 可能每 200ms 触发一次,你 1 秒采一次根本抓不到。

  • 推荐命令:jstat -gccause <pid> 200 50(每 200ms 采一次,共 50 次,覆盖 10 秒窗口)
  • 重点盯 CGCC 列连续出现的非 No GC 值,比如反复出现 Metadata GC Threshold,说明 Metaspace 长期处于临界状态
  • 别只看最后一行——GC 原因可能在第 3 行就首次暴露,后面几行只是重复;要扫完整输出,尤其关注第一次非 No GC 出现的位置
  • 如果 CGCCSystem.gc(),立刻检查代码里有没有 System.gc() 或启用了 -XX:+ExplicitGCInvokesConcurrent

看到 Metadata GC Threshold 后该做什么

这不是警告,是已发生的事实:JVM 已经因为 Metaspace 不足触发了 GC,且大概率失败了(否则不会继续报这个原因),接下来可能频繁 Full GC 或 OOM。

  • 先确认 Metaspace 当前配置:jinfo -flag MaxMetaspaceSize <pid>,如果输出 -XX:MaxMetaspaceSize=-1(即不限制),反而更危险——它会不断扩容直到耗尽本地内存
  • 对比 MC(Metaspace 容量)和 MU(已使用):如果 MU / MC > 0.95,基本就是瓶颈
  • 临时缓解可加:-XX:MaxMetaspaceSize=256m -XX:MetaspaceSize=128m(设初始值避免频繁扩容)
  • 根因排查得结合 jmap -clstats <pid> 看类加载器数量,或用 jcmd <pid> VM.native_memory summary 查 native 内存是否被 class metadata 占满

真正容易被忽略的是:Metaspace GC 不会释放所有元数据,只有**无引用的类加载器及其加载的类**才会被卸载。所以即使调大 MaxMetaspaceSize,如果存在 ClassLoader 泄漏(如 ThreadLocal 持有、OSGi、热部署框架残留),问题只会延后爆发。

标签:JS