JDK监控和故障处理工具总结
JDK 自带的诊断工具常被当成零散命令来背,其实它们各有分工。本文先给每个工具一个明确定位,再按线上最高频的三个场景——CPU 飙高、内存泄漏、死锁——把它们串成可复用的排查工作流。
工具定位速览
命令行工具
- jps:入口工具,列出当前用户可见的 Java 进程及 pid。
jps -l显示主类全名或 jar 路径,jps -v顺带打印 JVM 启动参数。一切排查从这里开始。 - jstat:轻量监控,持续观察类加载、内存、GC 的统计数据。
jstat -gcutil <pid> 1000每秒输出一次各代占用百分比与 GC 次数、耗时,是判断”GC 是否异常”的第一手数据;开销极小,适合在生产环境长时间挂起观察。 - jstack:生成线程快照,回答”每个线程此刻在干什么、在等什么锁”,用于定位死锁、线程阻塞与接口无响应。
- jmap:生成堆转储快照,回答”堆里到底装了什么”。
jmap -dump:live,format=b,file=heap.hprof <pid>会先触发一次 Full GC 再导出存活对象——对大堆意味着一次明显停顿,生产环境务必挑低峰期执行。 - jcmd:JDK 7 起提供的多功能入口,一条命令集成多种诊断能力:
jcmd <pid> VM.flags查看生效参数,jcmd <pid> GC.heap_dump heap.hprof导出堆,jcmd <pid> VM.native_memory summary查看本地内存(需启动时加-XX:NativeMemoryTracking=summary)。记不住其他命令时,先jcmd <pid> help看它支持什么。
可视化工具
- JConsole:基于 JMX 的监控台,适合实时观察内存曲线与线程状态,线程页自带死锁检测按钮。
- VisualVM:多合一工具,整合监控、线程 dump、堆 dump 分析和方法级性能采样;Oracle JDK 9 起不再随包捆绑,需单独下载。
- Arthas:开源的在线诊断工具,attach 到运行中的进程后,无需重启即可 watch 方法入参与返回值、trace 调用链耗时、反编译查类来源,定位”这个接口为什么慢”比传统工具直接得多。常用
dashboard看概览、thread查线程、trace/watch跟方法。
场景一:CPU 飙高
目标是找到吃 CPU 的线程,以及它在执行什么代码:
top -H -p <pid> # 找到高 CPU 的线程号 |
如果热点线程名字带 GC 字样,说明问题不在业务代码而是内存压力,应转去查 GC 日志;如果是业务线程反复停在同一方法上,可用 Arthas 的 trace 进一步看耗时分布。单次 jstack 可能错过瞬时现场,间隔几秒多打几次对比,结论更可靠。
场景二:内存泄漏
目标是先确认泄漏存在,再找到泄漏的对象是谁。
- 观察趋势:
jstat -gcutil <pid> 5s持续观察。老年代占用(O 列)在每次 Full GC 后都降不下去、水位不断抬升,是泄漏的典型特征。 - 留存现场:挑低峰期导出堆快照:
jcmd <pid> GC.heap_dump /data/dumps/heap.hprof |
- 离线分析:把 dump 拉到本地,用 MAT 或 VisualVM 打开。MAT 的 Leak Suspects 报告会直接给出可疑对象与支配树(Dominator Tree),沿引用链找出谁在持有它们。
- 对比验证:条件允许时隔一段时间取两次 dump 对比,持续增长且始终无法回收的对象类型,基本就是泄漏源。
如果启动参数里开了 -XX:+HeapDumpOnOutOfMemoryError,OOM 发生时会自动留下 dump,但别等到那一天才做分析。
场景三:死锁
死锁的特征是相关线程全部 BLOCKED、应用 hang 住但 CPU 并不高。
jstack 会自动检测并报告死锁环:
jstack <pid> | grep -A 20 "Found.*deadlock" |
输出会明确列出每个线程在等哪把锁、锁又被谁持有,顺着栈帧找到加锁代码即可。图形界面里,JConsole 的”检测死锁”按钮、Arthas 的 thread -b(找出阻塞了其他线程的线程)都能快速定位。
修复层面,绝大多数死锁源于加锁顺序不一致:给全局锁约定统一的获取顺序,或改用带超时的 tryLock,都能从根上规避。
小结
- jps 找进程,jstat 看趋势,jstack 看线程,jmap 与 jcmd 看堆,可视化工具做交互分析,Arthas 做在线深度诊断。
- 三个场景是同一个套路:先确认现象(top、jstat),再抓现场(jstack、heap dump),最后离线分析定位根因。
- 各工具的子命令随 JDK 版本演进,以目标版本的
jcmd <pid> help和官方文档为准。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Dai Wei!
评论

