jcmd 1 JFR.start duration=60s filename=a.jfr
jfr print --events jdk.ExecutionSample a.jfr > s.txt
grep -v 'GC Thread' s.txt | head -50

CPU 打满时抓的火焰图,最宽的一段是 VM Thread 和 GC Worker,业务栈只剩薄薄一条,看不出慢在哪个方法。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:采样把 JVM 内部线程一起算进 CPU 占用,回收线程抢走大部分时间片,应用栈被压扁,不按线程名过滤的话,热点永远指向垃圾回收而不是业务代码。

围绕「火焰图 GC 线程」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。监控和日志的时间要对上,时区不一致会多绕很大一圈。

临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。

处理上按这个顺序:先对 GC 日志确认停顿时间和频率;按线程名过滤掉回收与编译线程;对剩余业务栈按方法聚合找热点。

确认没问题再收工,过滤后能指到具体业务方法,GC 占比和 GC 日志里的数字对得上。

作者 9823189