前言
jcmd 是 oracle jdk(java development kit)自 jdk 7 起引入的一个强大的诊断工具,用于与正在运行的 jvm(java virtual machine)实例进行交互。它允许用户执行各种诊断命令,比如线程堆栈分析、堆转储、gc 信息、类加载器统计等,非常适合在生产环境中对 java 应用程序进行调试和监控。
一、jcmd命令基本语法
jcmd <pid | main-class> <command> [options]
<pid>:目标 java 进程的进程 id。<main-class>:目标 java 应用的主类名(可以省略 jar 路径)。<command>:具体的诊断命令,比如vm.flags。[options]:命令附带的参数(具体取决于命令)。
二、查看可用的 java 进程
jcmd
输出
970 com.dzy.main 67890 org.apache.catalina.startup.bootstrap
表示当前有两个 java 进程在运行,它们的进程 id 分别是 970 和 67890。
三、常用命令详解与使用示例
1. 查看所有支持的命令
jcmd <pid> help
用法
jcmd 970 help
输出
列出该 jvm 实例支持的所有命令:
970: vm.version vm.command_line vm.flags thread.print gc.heap_info gc.run gc.class_histogram ...
2. 查看 jvm 版本信息
jcmd <pid> vm.version
用法
jcmd 970 vm.version
输出
970: java hotspot(tm) 64-bit server vm version 17.0.9+11-lts-201 jdk 17.0.9
3. 查看启动参数
jcmd <pid> vm.command_line
用法
jcmd 970 vm.command_line
输出
command line: -xmx2g -xms1g -dspring.profiles.active=prod -jar app.jar
4. 查看 jvm 参数(flags)
jcmd <pid> vm.flags
用法
jcmd 970 vm.flags
输出
-xx:initialheapsize=1073741824 -xx:maxheapsize=2147483648 -xx:+useg1gc
5. 打印线程堆栈(类似jstack)
jcmd <pid> thread.print
用法
jcmd 970 thread.print
输出
列出所有线程的栈信息,包括锁等待、阻塞等,非常适合死锁分析。
6. 强制触发 gc
jcmd <pid> gc.run
用法
jcmd 970 gc.run
此命令不会显示太多输出,但会触发一次完全 gc。
7. 获取堆信息(heap 使用情况)
jcmd <pid> gc.heap_info
用法
jcmd 970 gc.heap_info
输出
heap configuration:
minheapfreeratio = 40
maxheapfreeratio = 70
...
heap usage:
g1 heap:
regions = 2048
capacity = 2048m
used = 1024m
free = 1024m
8. 导出 heap dump(堆快照)
jcmd <pid> gc.heap_dump /path/to/heapdump.hprof
用法
jcmd 970 gc.heap_dump /tmp/app-heap.hprof
文件可以用 mat 或 visualvm 分析。
9. 类直方图(类实例计数)
jcmd <pid> gc.class_histogram
用法
jcmd 970 gc.class_histogram 或者输出到文件 jcmd 970 gc.class_histogram > histogram.txt
输出
num #instances #bytes class name ---------------------------------------------- 1: 10000 1600000 [c 2: 5000 800000 java.lang.string 3: 3000 720000 java.util.hashmap
10. 导出类加载器信息
jcmd <pid> vm.class_loader_stats
用法
jcmd 970 vm.class_loader_stats
输出
统计各类加载器加载的类数量、占用内存等信息。
11. 检查是否发生了死锁
jcmd <pid> thread.print
用法
jcmd 970 thread.print
系统会显示哪些线程在等待锁、拥有锁,如果存在死锁,会提示 found one java-level deadlock.
12. 查看 metaspace 使用情况
jcmd <pid> vm.native_memory summary
用法
jcmd 970 vm.native_memory summary
需要启动 jvm 时开启:
-xx:nativememorytracking=summary
13. 查看系统属性(类似 system.getproperties)
jcmd <pid> vm.system_properties
用法
jcmd 970 vm.system_properties
14. 使用 java flight recorder(jdk 11+)
jfr.start, jfr.dump, jfr.stop
# 启动 jfr jcmd 970 jfr.start name=profile settings=profile duration=60s filename=/tmp/recording.jfr # 手动 dump jcmd 970 jfr.dump name=profile filename=/tmp/manual.jfr # 停止 jfr jcmd 970 jfr.stop name=profile
15. 查看 jit 编译缓存区状态
jcmd <pid> compiler.codecache
用法
jcmd 970 compiler.codecache
四、常见场景使用
性能监控中查看当前内存使用情况
jcmd $(pidof java) gc.heap_info
导出内存快照进行 oom 分析
jcmd $(pidof java) gc.heap_dump /tmp/dump-$(date +%s).hprof
分析线程死锁或阻塞线程
jcmd $(pidof java) thread.print > /tmp/thread-dump.log
定时触发 gc 以排查内存回收异常
watch -n 60 "jcmd $(pidof java) gc.run"
java 服务卡顿,想排查是否 gc 频繁
jcmd <pid> gc.heap_info jcmd <pid> gc.class_histogram jcmd <pid> gc.run jcmd <pid> gc.class_histogram
比较前后对象数量是否减少,分析垃圾回收效率。
服务 cpu 飙高,定位是哪条线程
- 查看线程信息(找到耗 cpu 的线程)
top -hp <pid>
- 将该线程 tid 转为十六进制(假设是 970 → 0x3039)
print "%x/n" <pid>
- 在
jcmd输出中查找栈
jcmd <pid> thread.print | grep -a 20 0x3039
导出类实例占用查看内存增长
jcmd <pid> gc.class_histogram > before.txt # 10分钟后 jcmd <pid> gc.class_histogram > after.txt diff before.txt after.txt
分析 jvm 启动参数差异
jcmd <pid> vm.flags jcmd <pid> vm.command_line
五、注意
jcmd只能对当前用户启动的 java 进程使用,或者以root权限运行。- 输出信息比较多,建议重定向到文件进行分析。
- 和
jstack、jmap等相比,jcmd更统一、更高效。
| 功能 | 命令 |
|---|---|
| 查看进程列表 | jcmd |
| 查看支持命令 | jcmd <pid> help |
| jvm 版本 | jcmd <pid> vm.version |
| jvm 启动参数 | jcmd <pid> vm.command_line / vm.flags |
| 手动 gc | jcmd <pid> gc.run |
| 打印线程堆栈 | jcmd <pid> thread.print |
| 类占用分析 | jcmd <pid> gc.class_histogram |
| 原生内存 | jcmd <pid> vm.native_memory summary |
| 启动/导出 jfr | jcmd <pid> jfr.* |
总结
到此这篇关于jvm之jcmd命令详解的文章就介绍到这了,更多相关jvm jcmd命令内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论