简单介绍
JDK1.7之后新增的一个命令,大型真香现场。 基本结合了jmap, jstat, jstack, jps, jinfo
等常用命令,使用起来比较方便简单。
一个可以发送诊断命令给JVM的工具,对控制Java飞行记录器、故障排除、JVM诊断和java应用诊断比较有用。
PS:jcmd只能用在与正在运行的JVM实例的机器上,并且必须要有JVM启动时的用户权限。 即:jcmd不能用于远程诊断。
语法
jcmd [ -l | -h | -help ]
jcmd <pid|main-class> PerfCounter.print
jcmd <pid|main-class> -f filename
jcmd <pid|main-class> command [ arguments]
jcmd后可以跟pid,也可以跟主函数名称。这里需要注意的是,main-class并不是指打包的jar包里面的Main-Class所指的信息。而是指当前ps -ef | grep xxx
得到的进程信息里面的关键字。
比如,以halo博客为例。
启动脚本如下为:
/opt/soft/jdk18/jdk1.8.0_101/bin/java -Xms512m -Xmx512m -XX:NativeMemoryTracking=summary -jar halo-1.2.0.jar
使用JD-JUI反编译halo的代码,查看MANIFEST.MF,发现Main-Class为:org.springframework.boot.loader.JarLauncher
如下图:
当我们使用jcmd org.springframework.boot.loader.JarLauncher help
命令的时候,发现提示找不到。如下图:
但当我们使用jcmd halo help
的时候,反而能得到具体的信息。如下图
所以,main-class指的是java进程的关键字,能唯一找到java进程的关键字。
另外: jcmd 5121 help
和 jcmd halo help
的作用是一样的,如下图:(PS:5121为halo进程的pid)
PS:
建议使用pid的方式,能更准确的调试需要的进程。
参数说明
jcmd [ -l | -h | -help ]
jcmd
和jcmd -l
等价于jps
,列出当前运行中的java进程。
jcmd -h
和jcmd -help
显示当前命令的帮助文档
jcmd <pid|main-class> PerfCounter.print
jcmd的一个特殊命令,可以打印目标进程上所有的性能计数器。
jcmd <pid|main-class> -f filename
从文件中读取命令,并在目标进程上执行。
一个命令一行,#
表示注释。当读完所有行(命令)或者遇到stop关键字的时候,则停止读取,文件处理完成。
暂时没有实际使用到的场景,猜测的使用场景为,定期的去做jvm进程监测的时候,可以通过这种方式来批量处理。
jcmd <pid|main-class> command [ arguments]
这是比较常用的命令语法。
jcmd帮助命令
jcmd pid help
可以查看当前进程上可用的命令。如下图:
针对每个命令,可以使用 jcmd pid help <command>
的方式查看具体每个命令的帮助文档,如下图:
几个实用的jcmd命令
命令 | 说明 | 替代命令 |
---|---|---|
jcmd pid VM.version | 查看当前JVM的版本信息 | 相当于:jinfo -sysprops |
jcmd pid VM.system_properties | 查看当前进程JVM的属性信息 | 相当于:jinfo -sysprops |
jcmd pid VM.flags | 打印当前JVM参数信息,如果没有JVM参数,也会打印一些默认值,比如初始堆大小 | 相当于jinfo -flags |
jcmd pid VM.uptime | 打印系统运行的时间 | |
jcmd pid GC.class_histogram jcmp pid GC.class_histogram filename=histogram.histo |
打印class的直方图 | 相当于jmap -histo pid |
jcmd pid GC.heap_dump filename=dump.bin | dump堆转储。注意:filename默认存储位置是当前java进程启动脚本所在目录。 | 相当于jmap -dump:live,format=b,file=heap.bin pid |
jcmd pid Thread.print | 打印堆栈信息 | 相当于jstack pid |
jcmd pid VM.command_line | 查看当前的JVM启动命令行信息 | 相当于 jinfo -sysprops |
jcmd pid GC.run_finalization | 对JVM执行System.runFinalization()函数 | |
jcmd pid GC.run | 对JVM执行System.gc()函数。之前LinuxTop RES和JVM XMS关系文章里面提到的手动触发FullGC,也可以通过这种方式来触发 |
JFR
针对JVM飞行器记录的一些命令。关于飞行器记录,可以参考官网Java Fight Recorder
命令 | 说明 |
---|---|
jcmd pid JFR.start name=<name> duration=120s filename=<jfrfilename> | 启动JFR,eg: jcmd 5121 JFR.start name=jfrDemo duration=120s filename=jfrDemp.jfr 启动JFR录制,并在120s之后,将其保存到java进行启动目录下的jfrDemo.jfr文件中 注意:如果 JFR.start 不跟filename 和duration 参数的话,则需要JFR.dump 命令来停止记录并做转储。 |
jcmd pid JFR.dump name=<name> filename=<jfrfilename> | 执行dump,需要先执行JFR.start。filename必须以jfr结尾 eg: jcmd 5121 JFR.dump name=jfrDemo filename=jrfDemo.jfr |
jcmd pid JFR.check | 检查当前正在运行的飞行器记录 |
jcmd pid JFR.stop | 停止飞行器记录,数据将会丢失 |
PS:
java飞行记录器需要解锁commercial features 才可以用。
使用
jcmd pid VM.unlock_commercial_features
可以解锁。
JFR的使用例子:
[root@AY1312180952417614c9Z ~]# jcmd 5121 JFR.start name=jfrDemo duration=120s filename=jfrDemp.jfr
5121:
Java Flight Recorder not enabled.
Use VM.unlock_commercial_features to enable.
[root@AY1312180952417614c9Z ~]# jcmd 5121 VM.unlock_commercial_features
5121:
Commercial Features now unlocked.
[root@AY1312180952417614c9Z ~]# jcmd 5121 JFR.start name=jfrDemo duration=120s filename=jfrDemp.jfr
5121:
Started recording 1. The result will be written to:
/opt/web/blog/jfrDemp.jfr
[root@AY1312180952417614c9Z ~]# jcmd 5121 JFR.check
5121:
Recording: recording=1 name="jfrDemo" duration=2m filename="jfrDemp.jfr" compress=false (running)
[root@AY1312180952417614c9Z blog]# jcmd 5121 JFR.check
5121:
Recording: recording=1 name="jfrDemo" duration=2m filename="jfrDemp.jfr" compress=false (stopped)
JFR的文件需要使用jmc来查看。
关于JFR实操,osx下的jmc启动有问题,后面有机会的话,找个案例实际试验一下。