JVM 统一诊断工具 `jcmd` 使用
JVM 统一诊断工具 jcmd 使用
jcmd(Java Command)是 JDK 7u40 引入的命令行工具,它允许用户向运行中的 Java 虚拟机发送诊断命令。在 JDK 9 以后,jcmd 更是成为了标准诊断的首选工具。
1. 基础用法与命令发现
1.1 列出所有 Java 进程
不带任何参数执行 jcmd,可以列出所有正在运行的 Java 进程及其 PID:
jcmd
输出示例:
Plaintext
12345 DemoApplication.jar
67890 org.jetbrains.idea.Main
1.2 查看可用命令
向特定的 PID 发送 help 命令,可以查看该 JVM 实例当前支持的所有诊断命令。
jcmd <PID> help
# 示例:jcmd 12345 help
输出示例(部分):
Plaintext
The following commands are available:
JFR.start
JFR.stop
JFR.dump
Thread.print
GC.heap_dump
GC.class_histogram
VM.uptime
...
1.3 查看具体命令的帮助信息
可以针对某个具体的命令获取更详细的参数说明。
jcmd <PID> help <CommandName>
# 示例:jcmd 12345 help GC.heap_dump
2. 核心功能及传统工具替代
jcmd 通过不同的命令,实现了对传统工具的全面替代。
2.1 线程分析 (替代 jstack)
用于获取线程堆栈信息,排查死锁、高 CPU 占用等问题。
| 传统工具 | jcmd 命令 | 作用 |
|---|---|---|
jstack <PID> |
Thread.print |
打印线程堆栈(默认包含锁信息)。 |
jstack -l <PID> |
Thread.print -l |
注意:-l 参数作为 Thread.print 的子参数传递。 |
示例:
# 获取线程堆栈,包含锁信息(等同于 jstack -l)
jcmd 12345 Thread.print -l
提示:
jcmd Thread.print的输出格式与jstack完全一致,因此前一节介绍的堆栈分析方法依然适用。
2.2 堆与内存分析 (替代 jmap & jstat)
用于检查堆内存使用情况、查看对象分布或生成堆转储文件。
| 传统工具 | jcmd 命令 | 作用 |
|---|---|---|
jmap -dump |
GC.heap_dump |
生成堆转储文件(HPROF 文件),用于离线分析内存泄漏。 |
jmap -histo |
GC.class_histogram |
打印类实例数量和占用的字节数,用于识别内存大户。 |
jstat -gc |
GC.heap_info |
打印 GC 概况和堆区(Eden, Old, Survivor)信息。 |
示例:
# 1. 生成堆转储文件到指定位置 (必须是绝对路径)
jcmd 12345 GC.heap_dump /tmp/my_app_dump.hprof
# 2. 打印当前活跃对象直方图
jcmd 12345 GC.class_histogram
# 3. 查看堆内存详细信息
jcmd 12345 GC.heap_info
2.3 虚拟机管理 (VM)
提供了一些虚拟机运行时信息的查询和操作。
| 命令 | 作用 |
|---|---|
VM.version |
打印 JVM 版本和参数。 |
VM.uptime |
打印 JVM 启动时长(已运行时间)。 |
VM.system_properties |
打印所有系统属性(System Properties)。 |
VM.commercial_features |
打印所有商业功能(如 JFR/JMC)的状态。 |
GC.run |
手动触发 Full GC。生产环境谨慎使用。 |
示例:
# 查看 JVM 已经运行了多长时间
jcmd 12345 VM.uptime
3. Java Flight Recorder (JFR) 控制 (独有功能)
Java Flight Recorder 是 Oracle 提供的低开销生产环境性能分析工具。jcmd 是管理 JFR 记录的主要工具。
3.1 启动 JFR 记录
指定记录名称、配置文件和输出路径:
jcmd <PID> JFR.start name=MyRec duration=60s settings=profile
# name: 记录的名称 (MyRec)
# duration: 持续时间 (60秒后自动停止)
# settings: 使用 JDK 自带的 profile 模板 (高细节)
3.2 停止并导出记录
如果记录是无限期启动的,你需要手动停止并导出数据:
jcmd <PID> JFR.stop name=MyRec filename=/tmp/my_rec_data.jfr
3.3 其他 JFR 命令
JFR.dump: 导出当前正在进行的记录数据,但不停止记录。JFR.check: 检查当前正在进行的 JFR 记录状态。
4. 最佳实践总结
| 场景 | 推荐 jcmd 命令 | 目的 |
|---|---|---|
| 高 CPU | jcmd <PID> Thread.print -l |
配合 top -Hp 定位高耗时线程的堆栈。 |
| 内存泄漏 | jcmd <PID> GC.heap_dump /path/to/file.hprof |
生成堆转储文件,使用 MAT 或 VisualVM 分析。 |
| 并发卡顿 | jcmd <PID> Thread.print -l (多次采样) |
查找大量的 BLOCKED 或 WAITING 状态线程。 |
| 性能基准测试 | jcmd <PID> JFR.start ... |
在低开销下获取细粒度的 CPU、锁、IO 等性能数据。 |

浙公网安备 33010602011771号