定位高CPU线程需用top -H -p 找TID,转十六进制后在jstack快照中搜索,重点分析RUNNABLE状态下的顶层Java调用栈,并结合jstat、JFR、Prometheus+Grafana及Arthas进行持续监控与验证。

监控和分析 JVM 线程的 CPU 开销,核心是定位哪些线程在持续占用 CPU、处于什么状态、执行哪段代码。这不是看整体 JVM CPU 使用率,而是下钻到线程级,结合状态、堆栈、时间维度做交叉判断。
用 top + jstack 定位高 CPU 线程
这是最常用、最轻量的线上排查组合:
- 执行 top -H -p
,按 P(大写)降序排列,找出 %CPU 最高的线程 ID(TID) - 将该 TID 转为十六进制(例如:12345 → 0x3039),便于后续匹配
- 执行 jstack
> thread_dump.txt 获取完整线程快照 - 在文件中搜索 0x3039,找到对应线程块,重点看其状态是否为 RUNNABLE,以及最顶层的 Java 方法调用栈
关注线程状态与真实执行意图
不能只看“RUNNABLE”就断定它在干活——JVM 中的 RUNNABLE 包含操作系统层面的 Ready(等待调度)和 Running(正在执行)。真正消耗 CPU 的,通常是:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 无限循环或计算密集型逻辑(如 JSON 序列化、正则匹配、加密解密)
- 自旋等待(比如未加锁的 volatile 检查 + while 循环)
- 频繁的 synchronized 争抢导致线程反复进出临界区
- 阻塞 I/O 未超时,但底层驱动卡住(较少见,需结合 strace 辅助)
借助 jstat 和可视化工具辅助验证
单次 jstack 只能抓瞬时快照,容易漏掉间歇性热点。建议配合周期性指标观察:
- 运行 jstat -gc
1000 5 查看 GC 是否频繁触发(间接影响线程调度) - 用 jstat -compiler
看 JIT 编译是否异常(如大量方法未被编译,可能说明热点不稳) - 在开发或预发环境,启用 JFR(Java Flight Recorder)并录制 60 秒:java -XX:+FlightRecorder -XX:StartFlightRecording=duration=60s,filename=recording.jfr MyApp,之后用 JDK 自带的 JDK Mission Control 打开,可直观看到各线程的 CPU 时间占比、方法热点火焰图
生产环境更稳妥的长期观测方式
避免每次问题爆发才临时登录服务器:
- 通过 Prometheus + JMX Exporter 持续采集
jvm_threads_current、jvm_threads_states_threads(按状态分类计数)、process_cpu_seconds_total等指标 - 配置 Grafana 面板,对 RUNNABLE 线程数突增 或 单线程 CPU 时间占比 > 80% 设置告警
- 集成 Arthas,在线执行 thread -n 5 查看 CPU 使用率 Top 5 的线程及其栈,支持实时刷新

















