jcmd是JDK自帶的調試工具,具備很是強大的功能。jcmd是JDK7中正式引入的,有了jcmd,徹底能夠替換不少經常使用的其餘工具,好比jstak和jmap。java
jcmd能夠將具體的診斷命令發送給JVM。爲了安全起見,使用jcmd的用戶必須跟運行的java程序具備一樣的用戶和用戶組。docker
jcmd的調試命令有不少種,每一種調試命令又有本身的參數。安全
本文將會結合具體的例子詳細講解jcmd的使用。工具
jcmd的語法比較簡單:性能
jcmd [pid | main-class] command... | PerfCounter.print | -f filename
jcmd [-l]
jcmd -h
複製代碼
pid和main-class是二選一:spa
其中pid表示要發送診斷命令的java進程id。調試
也能夠指定main-class,表示要發送診斷命令給運行該main-class的java進程。code
command表示能夠在jcmd中運行的命令,咱們看下jcmd支持哪些命令:orm
./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 表示幫助。
下面咱們舉幾個經常使用的例子
./jcmd -l
98109 jdk.jcmd/sun.tools.jcmd.JCmd -l
複製代碼
經過使用jcmd -l能夠列出全部正在運行的JVM進程。跟jps是同樣的。
使用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
複製代碼
使用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裏面到底有什麼,則能夠經過下面的命令將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中各個對象的使用狀況,則能夠下面方法:
./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)
複製代碼
上面的結果很是有用,在一些性能調試方法能夠起到意想不到的做用。
jcmd還支持jfr功能。JFR的全稱叫作Java Flight Recorder。你能夠將其看作是JVM中一些事件的記錄器。
有關JFR的更多內容,將會在個人下一篇文章中詳細講解。
jcmd還有不少其餘的功能,你們能夠多用多探索。
本文做者:flydean程序那些事
本文連接:www.flydean.com/jdk14-jcmd/
本文來源:flydean的博客
歡迎關注個人公衆號:程序那些事,更多精彩等着您!