JVM 性能监控工具实战
JDK 自带的命令行工具是 JVM 排查的第一梯队。它们随 JDK 发行、零额外依赖,适合线上环境快速定位问题。本系列逐款讲解命令用法与典型场景。
jps — 进程查看
列出本机 Java 进程及其参数:
bash
jps -l # 显示完整主类名 / jar 路径
jps -v # 显示传给 JVM 的参数
jps -m # 显示 main 方法参数$ jps -lv
12345 demo.jar -Xmx2g -XX:+UseG1GC -Dspring.profiles.active=prod作用:快速找到目标进程 PID,是其他工具的前置步骤。
jstat — 类加载与 GC 统计
实时查看类加载、编译与 GC 数据,是观察 GC 行为的主力工具:
bash
jstat -class <pid> # 类加载统计
jstat -compiler <pid> # JIT 编译统计
jstat -gc <pid> 1000 10 # GC 统计,每 1 秒采样,共 10 次
jstat -gcutil <pid> 1000 # 各代空间使用率(百分比)
jstat -gccause <pid> # 附加显示最近 GC 原因-gcutil 输出解读:
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 50.00 65.32 25.12 92.15 90.32 128 2.540 5 1.200 3.740| 列 | 含义 |
|---|---|
| S0/S1/E/O | Survivor0/Survivor1/Eden/Old 使用率 |
| M/CCS | 元空间 / 类压缩空间使用率 |
| YGC/YGCT | Young GC 次数 / 总耗时(秒) |
| FGC/FGCT | Full GC 次数 / 总耗时 |
| GCT | GC 总耗时 |
排查要点:FGC 频繁 + O 高位 → 老年代压力大;YGCT 突增 → 新生代过大或晋升过快。
jmap — 堆信息与堆转储
查看堆内存详情与生成堆转储文件:
bash
jmap -heap <pid> # 堆配置与使用概览(含 GC 算法、各代大小)
jmap -histo <pid> # 堆对象直方图(类名、实例数、占用字节)
jmap -histo:live <pid> # 先 Full GC 再统计存活对象(生产慎用,会 STW)
jmap -dump:format=b,file=heap.hprof <pid> # 堆转储(生产慎用)
jmap -clstats <pid> # 类加载器统计典型用法:用 -histo 快速定位占用最大的类,决定是否需要转储深入分析。
jstack — 线程堆栈
导出线程栈,定位死锁、线程阻塞、CPU 飙高:
bash
jstack <pid> # 输出全部线程栈
jstack -l <pid> # 含锁信息(查找死锁)
jstack <pid> > thread.dump # 重定向保存线程状态分类:
| 状态 | 含义 | 排查方向 |
|---|---|---|
| RUNNABLE | 运行中 | 若长期在某个方法,可能是 CPU 密集 |
| BLOCKED | 等待锁 | 看等待哪把锁,找持锁线程 |
| WAITING / TIMED_WAITING | 等待 | 池化线程的常态,注意大量堆积 |
| DEADLOCK | 死锁(-l 输出) | 释放锁顺序问题 |
排查案例:应用卡死 → jstack 看到多个线程 BLOCKED 等待同一把锁 → 找到持锁线程的调用栈,定位到慢 SQL 或死循环。
jinfo — 运行时参数查看
查看/修改 JVM 参数与系统属性:
bash
jinfo <pid> # 全部参数与系统属性
jinfo -flags <pid> # 仅 JVM 参数
jinfo -sysprops <pid> # 仅系统属性
jinfo -flag MaxHeapSize <pid> # 查看单个参数用于确认线上进程实际生效的参数(如 -Xmx、GC 算法),排查"配置没生效"问题。
jcmd — 多功能命令入口
JDK 7+ 提供的统一诊断入口,覆盖多数工具能力:
bash
jcmd <pid> help # 列出该进程支持的所有命令
jcmd <pid> VM.flags # 查看 JVM 参数
jcmd <pid> GC.heap_info # 堆信息
jcmd <pid> GC.class_histogram # 对象直方图(等效 jmap -histo)
jcmd <pid> Thread.print # 线程栈(等效 jstack)
jcmd <pid> VM.uptime # 运行时长
jcmd <pid> GC.run # 触发 Full GC(慎用)
jcmd <pid> JFR.start # 启动 JFR 录制jcmd 优先于 jmap/jstack,因为它基于统一诊断命令机制,且对高版本 JDK 支持更完整。
jhsdb — 调试级工具
用于进程已崩溃或无法用常规工具连接时的底层分析:
bash
jhsdb jmap --pid <pid> # 对崩溃 JVM 生成堆信息
jhsdb jstack --pid <pid> # 线程栈
jhsdb jinfo --pid <pid> # 配置信息
jhsdb hsdb <pid> # 交互式调试器(图形界面)场景:OutOfMemoryError 后进程崩溃、常规 jcmd/jmap 无法连接时,用 jhsdb 事后分析。
组合排查流程
一次典型的线上 GC 排查:
1. jps -l 找到进程 PID
2. jstat -gccause <pid> 看 GC 频率、原因与代使用率
3. jmap -histo <pid> 看大对象分布
4. jstack <pid> 若伴随卡顿,看线程状态
5. jmap -dump ... 转储 确认问题后深入分析(MAT 等)
6. jcmd <pid> JFR.start 需要长期数据时用 JFR 录制原则:先看现象与频率(jstat),再定位对象与线程(jmap/jstack),最后转储深挖(MAT)。生产环境慎用会触发 STW 的命令(-histo:live、-dump)。