jcmd可直接完成大部分jvm诊断,无需额外工具或重启应用;关键步骤是先用jcmd -l精准定位进程pid和主类,再根据需求选用thread.print、gc.class_histogram、vm.native_memory summary等命令,并确认nmt等启动参数已启用。

直接用 jcmd 就能完成大部分 JVM 诊断,不用额外装工具,也不用重启应用。关键在于先找准进程、再选对命令、注意启动参数是否支持。
查进程 PID 和确认目标 JVM
别一上来就输 jcmd 12345 xxx——得先知道 12345 是不是你要的进程。
-
jcmd -l是最可靠的方式,输出格式为 PID 主类名或 jar 路径(比如12345 /opt/app.jar),比ps aux | grep java更准,能过滤掉 shell 包装脚本或非 JVM 进程 - 如果只看到数字没类名,说明用了自定义 Launcher 或混淆了主类,可查
cat /proc/12345/cmdline看真实启动命令 - 容器里运行时,确保
/tmp可写、挂载了/proc,否则jcmd -l可能为空或报错 - 若进程不可见,检查是否加了
-XX:+DisableAttachMechanism,或当前用户权限不足(需切到对应用户或用sudo jcmd,但生产环境慎用)
快速查看内存对象分布(直方图)
想看哪些类占内存多、实例数是否异常增长,用 GC.class_histogram,它相当于 jmap -histo:live,但更轻量。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 执行:
jcmd <pid> GC.class_histogram</pid> - 输出含三列:实例数、字节数、类名,按字节数倒序排列,一眼就能发现“内存大户”
- 注意:这个命令会触发一次 Full GC,线上高负载服务慎用;如需避免 GC,可用
jcmd <pid> VM.class_hierarchy</pid>查类加载关系(不触发 GC) - 如果提示
Command not found,说明 JDK 版本低于 8u121,该命令不支持
配合原生内存分析定位泄漏
堆外内存问题(如 DirectByteBuffer、JNI 库、JIT 缓存)光看堆直方图不够,得结合原生内存视图。
- 先确认 JVM 启动时加了
-XX:NativeMemoryTracking=summary(没加会报Native memory tracking is not enabled) - 执行:
jcmd <pid> VM.native_memory summary</pid>,1 秒内返回总用量和各模块占比 - 重点关注
[thread](线程数失控)、[class](动态生成类未释放)、[internal](DirectByteBuffer 等)是否持续增长 - 需要详细调用栈时才用
detail,但开销较大,高负载时慎用
其他高频诊断动作
日常排查常搭配使用这些命令:
-
jcmd <pid> Thread.print</pid>:获取线程堆栈,等价于jstack,但更稳定(不卡在 IN_NATIVE 状态) -
jcmd <pid> VM.flags -all</pid>:查所有生效 JVM 参数,包括自动推导值(如-XX:MaxRAMPercentage算出的堆大小) -
jcmd <pid> VM.system_properties</pid>:查-D参数,比如spring.profiles.active、file.encoding -
jcmd <pid> help</pid>:列出当前 JVM 支持的所有命令,不同 JDK 版本略有差异
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










