深入浅析jcmd:JDK14中的调试神器
jcmd是JDK自带的调试工具,具有非常强大的功能。jcmd是JDK7中正式引入的,有了jcmd,完全可以替换很多常用的其他工具,比如jstak和jmap。
jcmd可以将具体的诊断命令发送给JVM。为了安全起见,使用jcmd的用户必须跟运行的java程序具有同样的用户和用户组。
jcmd的调试命令有很多种,每一种调试命令又有自己的参数。
本文将会结合具体的例子详细讲解jcmd的使用。
jcmd的语法
jcmd的语法比较简单:
jcmd[pid|main-class]command...|PerfCounter.print|-ffilename jcmd[-l] jcmd-h
pid和main-class是二选一:
其中pid表示要发送诊断命令的java进程id。
也可以指定main-class,表示要发送诊断命令给运行该main-class的java进程。
command表示可以在jcmd中运行的命令,我们看下jcmd支持哪些命令:
./jcmd93989help 93989: Thefollowingcommandsareavailable: Compiler.CodeHeap_Analytics Compiler.codecache Compiler.codelist Compiler.directives_add Compiler.directives_clear Compiler.directives_print Compiler.directives_remove Compiler.queue GC.class_histogram GC.class_stats GC.finalizer_info GC.heap_dump GC.heap_info GC.run GC.run_finalization JFR.check JFR.configure JFR.dump JFR.start JFR.stop JVMTI.agent_load JVMTI.data_dump ManagementAgent.start ManagementAgent.start_local ManagementAgent.status ManagementAgent.stop Thread.print VM.class_hierarchy VM.classloader_stats VM.classloaders VM.command_line VM.dynlibs VM.events VM.flags VM.info VM.log VM.metaspace VM.native_memory VM.print_touched_methods VM.set_flag VM.stringtable VM.symboltable VM.system_properties VM.systemdictionary VM.uptime VM.version help
Perfcounter.print表示要打印java进程暴露的performancecounters。
-ffilename表示从文本文件中读取要运行的命令。
-l列出不是运行在docker中JVM。
-h表示帮助。
下面我们举几个常用的例子
列出运行的JVM
./jcmd-l 98109jdk.jcmd/sun.tools.jcmd.JCmd-l
通过使用jcmd-l可以列出所有正在运行的JVM进程。跟jps是一样的。
打印stack信息
使用jcmdpidThread.print-l可以打印出java程序的stack信息。其中-l表示输出java.util.concurrent的lock信息。
下面看个简单的例子:
./jcmd93989Thread.print-l FullthreaddumpJavaHotSpot(TM)64-BitServerVM(14.0.1+7mixedmode,sharing): ThreadsclassSMRinfo: _java_thread_list=0x00007fbeb1c4cb10,length=12,elements={ 0x00007fbeb282a800,0x00007fbeb282d800,0x00007fbeb282e800,0x00007fbeb2830800, 0x00007fbeb2831800,0x00007fbeb2832000,0x00007fbeb2833000,0x00007fbeb3831000, 0x00007fbeb3822000,0x00007fbeb3174000,0x00007fbeb3815000,0x00007fbeb226f800 } "ReferenceHandler"#2daemonprio=10os_prio=31cpu=0.64mselapsed=8996.59stid=0x00007fbeb282a800nid=0x4703waitingoncondition[0x000070000440d000] java.lang.Thread.State:RUNNABLE atjava.lang.ref.Reference.waitForReferencePendingList(java.base@14.0.1/NativeMethod) atjava.lang.ref.Reference.processPendingReferences(java.base@14.0.1/Reference.java:241) atjava.lang.ref.Reference$ReferenceHandler.run(java.base@14.0.1/Reference.java:213) Lockedownablesynchronizers: -None
打印heapinfo
使用jcmdpidGC.heap_info可以获得heapinfo。
./jcmd93989GC.heap_info 93989: garbage-firstheaptotal71680K,used34410K[0x00000007d4400000,0x0000000800000000) regionsize1024K,20young(20480K),4survivors(4096K) Metaspaceused23810K,capacity24246K,committed24752K,reserved1071104K classspaceused2850K,capacity3015K,committed3072K,reserved1048576K
打印heapdump
如果想知道heap里面到底有什么,则可以通过下面的命令将heapdump出来:
./jcmd93989GC.heap_dumpheap_dump.out 93989: Dumpingheaptoheap_dump.out... Heapdumpfilecreated[27727979bytesin0.643secs]
heapdump需要传入一个文件名,存放dump出来的信息。
统计heap使用情况
有时候我们需要统计一下heap中各个对象的使用情况,则可以下面方法:
./jcmd93989GC.class_histogram 93989: num#instances#bytesclassname(module) ------------------------------------------------------- 1:2582611748304[B(java.base@14.0.1) 2:22331971800[I(java.base@14.0.1) 3:5154614928java.lang.Class(java.base@14.0.1) 4:24757594168java.lang.String(java.base@14.0.1) 5:4491439432[Ljava.lang.Object;(java.base@14.0.1) 6:13177421664java.util.concurrent.ConcurrentHashMap$Node(java.base@14.0.1) 7:5025160800java.util.HashMap$Node(java.base@14.0.1) 8:8793140688java.lang.Object(java.base@14.0.1) 9:212103584[Ljava.util.concurrent.ConcurrentHashMap$Node;(java.base@14.0.1)
上面的结果非常有用,在一些性能调试方法可以起到意想不到的作用。
JFR功能
jcmd还支持jfr功能。JFR的全称叫做JavaFlightRecorder。你可以将其看做是JVM中一些事件的记录器。
有关JFR的更多内容,可以点击查阅:https://www.nhooo.com/article/185648.htm
https://www.nhooo.com/article/185707.htm
到此这篇关于深入浅析jcmd:JDK14中的调试神器的文章就介绍到这了,更多相关jcmd:JDK14调试神器内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!