常用的 JVM 性能监控和故障排查命令行工具有哪些?(jps、jstat、jinfo、jmap、jstack、jcmd 等)
在 Java 开发和运维中,JDK 自带的命令行工具是进行 JVM 性能监控和故障排查(如内存泄漏、CPU 飙高、死锁等)的利器。这些工具通常位于 JDK 的 bin 目录下。
以下是常用 JVM 故障排查命令行工具的详细介绍及常用命令:
1. jps (JVM Process Status Tool) - 查看 Java 进程
作用: 类似于 Linux 的 ps 命令,但它只列出当前系统中的 Java 进程。这是排查的第一步,因为你需要通过它获取目标 Java 进程的 PID(进程 ID)。
常用命令:
jps:仅输出 PID 和类的简短名称。jps -l:输出主类的全名,如果进程执行的是 Jar 包,则输出 Jar 路径(最常用)。jps -v:输出启动时传递给 JVM 的参数(如-Xms,-Xmx等)。jps -m:输出传递给 Java 进程main()函数的参数。
示例: jps -lv
2. jstat (JVM Statistics Monitoring Tool) - 监控 JVM 统计信息
作用: 动态监控 JVM 的内存和垃圾回收(GC)情况,能在不生成快照的情况下查看实时运行状态。
基本语法: jstat -<option> <pid> [间隔时间/毫秒] [查询次数]
常用命令:
jstat -gcutil <pid> 1000 10:监控 GC 统计信息(百分比形式)。每隔 1000 毫秒(1秒)输出一次,共输出 10 次。- 重要输出列解释:
S0/S1:Survivor 区使用比例。E:Eden 区使用比例。O:Old(老年代)使用比例。M:Metaspace(元空间)使用比例。YGC/YGCT:年轻代 GC 次数及耗时。FGC/FGCT:Full GC 次数及耗时(排查卡顿的重点,FGC 过多说明有问题)。GCT:GC 总耗时。
- 重要输出列解释:
jstat -gc <pid>:与gcutil类似,但显示的是具体字节大小而不是百分比。
3. jinfo (Configuration Info for Java) - 查看和修改 JVM 配置参数
作用: 实时查看和调整虚拟机的各项参数。
常用命令:
jinfo -flags <pid>:查看所有 JVM 参数(包括默认参数和启动时显式指定的参数)。jinfo -sysprops <pid>:查看 Java 系统的System.getProperties()属性。jinfo -flag <参数名> <pid>:查看某个具体参数的值(如jinfo -flag MaxHeapSize 1234)。jinfo -flag [+|-]<参数名> <pid>:动态开启或关闭某些支持动态修改的布尔参数(如开启 GC 日志:jinfo -flag +PrintGCDetails <pid>)。
4. jmap (Memory Map for Java) - 导出内存映像(Heap Dump)
作用: 查看内存中的对象分布情况,或者生成堆内存快照(Dump 文件),是排查内存泄漏(OOM)最核心的工具。
常用命令:
jmap -dump:live,format=b,file=heap.hprof <pid>:生成堆内存快照。live:只 Dump 存活的对象(推荐,文件会小很多,但会触发一次 Full GC)。format=b:二进制格式。file=...:输出文件路径。- 注意:导出的
hprof文件通常使用 MAT (Memory Analyzer Tool) 或 VisualVM 进行可视化分析。
jmap -heap <pid>:打印堆的概要信息(堆的配置参数、各区域的内存使用情况)。(注:在 JDK 9+ 中建议使用jhsdb jmap -heap --pid <pid>)jmap -histo:live <pid>:打印堆中对象的统计信息(包含类名、实例数量、占用内存大小),轻量级排查内存问题时非常有用。
5. jstack (Stack Trace for Java) - 打印线程快照(Thread Dump)
作用: 生成当前时刻 JVM 中所有线程的堆栈跟踪信息。排查 CPU 占用过高、死锁、线程挂起等问题时的神器。
常用命令:
jstack -l <pid> > thread_dump.txt:打印所有线程的堆栈信息到文件中(-l会打印附加的锁信息)。
典型排查 CPU 飙高的思路:
- 用
top命令找到 CPU 占用最高的 Java 进程 PID。 - 用
top -H -p <pid>找到该进程中 CPU 占用最高的线程 TID。 - 将线程 TID 从十进制转为十六进制(如使用
printf "%x\n" <TID>)。 - 用
jstack <pid> | grep -A 20 <十六进制TID>找到具体的线程堆栈,查看是哪行代码在狂跑。
6. jcmd (JVM Diagnostic Command Tool) - 多功能“瑞士军刀”
作用: 从 JDK 7 开始引入,Oracle 官方强烈推荐的工具。它几乎包含了上面提到的 jstat、jinfo、jmap、jstack 的所有功能。
常用命令:
jcmd <pid> help:列出当前 JVM 支持的所有 jcmd 命令。- 替换
jps:jcmd -l(列出 Java 进程) - 替换
jstack:jcmd <pid> Thread.print(打印线程堆栈) - 替换
jmap -dump:jcmd <pid> GC.heap_dump /path/heap.hprof(导出堆内存快照) - 替换
jinfo:jcmd <pid> VM.flags(查看 JVM 参数)、jcmd <pid> VM.system_properties - 替换
jmap -histo:jcmd <pid> GC.class_histogram - 强制触发 GC:
jcmd <pid> GC.run
💡 总结与实战对照表
| 遇到什么问题 | 应该用什么工具 | 核心命令 | 目标 |
|---|---|---|---|
| 不知道进程ID | jps | jps -l |
获取 PID |
| 系统变卡/频繁停顿 | jstat | jstat -gcutil <pid> 1000 |
观察 Full GC 是否频繁,老年代是否满了 |
| CPU 占用 100% / 死锁 | jstack | jstack -l <pid> |
结合 top -H -p 找到占用 CPU 的代码行或死锁线程 |
| 内存溢出 (OOM) | jmap | jmap -dump:live,format=b,file=x.hprof <pid> |
导出堆快照交由 MAT 分析,找出大对象 |
| 想轻量级看下内存里啥最多 | jmap | jmap -histo:live <pid> | head -n 20 |
查看排名前 20 的类实例数量 |
| 需要修改或查看启动参数 | jinfo | jinfo -flags <pid> |
确认配置是否生效 |
| 全能替代方案 | jcmd | jcmd <pid> help |
一站式解决上述问题 |
额外推荐: 在现代 Java 开发中,除了上述 JDK 原生工具外,Arthas (阿尔萨斯)(阿里开源的 Java 诊断工具)在业内使用极广,支持反编译、动态修改代码、实时监控方法耗时等,可以说是进阶排查必备工具。