歡迎您光臨本站 註冊首頁

深入淺析jcmd:JDK14中的調試神器

←手機掃碼閱讀     zmcjlove @ 2020-05-04 , reply:0

jcmd是JDK自帶的調試工具,具有非常強大的功能。jcmd是JDK7中正式引入的,有了jcmd,完全可以替換很多常用的其他工具,比如jstak和jmap。
jcmd可以將具體的診斷命令發送給JVM。為了安全起見,使用jcmd的用戶必須跟運行的java程序具有同樣的用戶和用戶組。
jcmd的調試命令有很多種,每一種調試命令又有自己的參數。
本文將會結合具體的例子詳細講解jcmd的使用。
jcmd的語法
jcmd的語法比較簡單:
jcmd [pid | main-class] command... | PerfCounter.print | -f filename jcmd [-l] jcmd -h
pid和main-class是二選一:
其中pid表示要發送診斷命令的java進程id。
也可以指定main-class,表示要發送診斷命令給運行該main-class的java進程。
command表示可以在jcmd中運行的命令,我們看下jcmd支持哪些命令:
./jcmd 93989 help 93989: The following commands are available: 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進程暴露的performance counters。
-f filename表示從文本文件中讀取要運行的命令。
-l 列出不是運行在docker中JVM。
-h 表示幫助。
下面我們舉幾個常用的例子
列出運行的JVM
./jcmd -l 98109 jdk.jcmd/sun.tools.jcmd.JCmd -l
通過使用jcmd -l可以列出所有正在運行的JVM進程。跟jps是一樣的。
打印stack信息
使用jcmd pid Thread.print -l可以打印出java程序的stack信息。其中-l表示輸出java.util.concurrent的lock信息。
下面看個簡單的例子:
./jcmd 93989 Thread.print -l Full thread dump Java HotSpot(TM) 64-Bit Server VM (14.0.1+7 mixed mode, sharing): Threads class SMR info: _java_thread_list=0x00007fbeb1c4cb10, length=12, elements={ 0x00007fbeb282a800, 0x00007fbeb282d800, 0x00007fbeb282e800, 0x00007fbeb2830800, 0x00007fbeb2831800, 0x00007fbeb2832000, 0x00007fbeb2833000, 0x00007fbeb3831000, 0x00007fbeb3822000, 0x00007fbeb3174000, 0x00007fbeb3815000, 0x00007fbeb226f800 } "Reference Handler" #2 daemon prio=10 os_prio=31 cpu=0.64ms elapsed=8996.59s tid=0x00007fbeb282a800 nid=0x4703 waiting on condition [0x000070000440d000] java.lang.Thread.State: RUNNABLE at java.lang.ref.Reference.waitForReferencePendingList(java.base@14.0.1/Native Method) at java.lang.ref.Reference.processPendingReferences(java.base@14.0.1/Reference.java:241) at java.lang.ref.Reference$ReferenceHandler.run(java.base@14.0.1/Reference.java:213) Locked ownable synchronizers: - None
打印heap info
使用jcmd pid GC.heap_info可以獲得heap info。
./jcmd 93989 GC.heap_info 93989: garbage-first heap total 71680K, used 34410K [0x00000007d4400000, 0x0000000800000000) region size 1024K, 20 young (20480K), 4 survivors (4096K) Metaspace used 23810K, capacity 24246K, committed 24752K, reserved 1071104K class space used 2850K, capacity 3015K, committed 3072K, reserved 1048576K
打印heap dump
如果想知道heap裡面到底有什麼,則可以通過下面的命令將heap dump出來:
./jcmd 93989 GC.heap_dump heap_dump.out 93989: Dumping heap to heap_dump.out ... Heap dump file created [27727979 bytes in 0.643 secs]
heap dump需要傳入一個文件名,存放dump出來的信息。
統計heap使用情況
有時候我們需要統計一下heap中各個對象的使用情況,則可以下面方法:
./jcmd 93989 GC.class_histogram 93989: num #instances #bytes class name (module) ------------------------------------------------------- 1: 25826 11748304 [B (java.base@14.0.1) 2: 2233 1971800 [I (java.base@14.0.1) 3: 5154 614928 java.lang.Class (java.base@14.0.1) 4: 24757 594168 java.lang.String (java.base@14.0.1) 5: 4491 439432 [Ljava.lang.Object; (java.base@14.0.1) 6: 13177 421664 java.util.concurrent.ConcurrentHashMap$Node (java.base@14.0.1) 7: 5025 160800 java.util.HashMap$Node (java.base@14.0.1) 8: 8793 140688 java.lang.Object (java.base@14.0.1) 9: 212 103584 [Ljava.util.concurrent.ConcurrentHashMap$Node; (java.base@14.0.1)
上面的結果非常有用,在一些性能調試方法可以起到意想不到的作用。
JFR功能
jcmd還支持jfr功能。JFR的全稱叫做Java Flight Recorder。你可以將其看做是JVM中一些事件的記錄器。


[zmcjlove ] 深入淺析jcmd:JDK14中的調試神器已經有244次圍觀

http://coctec.com/docs/java/show-post-232809.html