本文內容過於硬核,建議有 Java 相關經驗人士閱讀。
1. 引言
雖然我們前面介紹了各種圖形化 JVM 故障處理工具,但是很多情況下,我們在處理問題的時候並沒有圖形化的操作環境可以使用,這時候,就需要用到 JDK 為我們提供的命令列工具了。
2. jps: 虛擬機器程式狀況工具
jps 絕對是使用頻率最高的 JDK 命令列工具,它的作用是可以列出正在執行的虛擬機器程式,並顯示虛擬機器執行主類( Main Class , main() 函式所在的類)名稱以及這些程式的本地虛擬機器唯一 ID ( LVMID , LocalVirtual Machine Identifier )。
命令格式:
jps [options ] [ hostid ]
執行樣例:
PS D:\> jps -l
5200 org.jetbrains.jps.cmdline.Launcher
16868 jdk.jcmd/sun.tools.jps.Jps
19368 org.jetbrains.idea.maven.server.RemoteMavenServer36
可以看到我本機,有三個 JVM 程式, 5200 和 19368 是軟體 IDEA 的程式,從類名上是可以看出來的,還有一個是 jps 本身的這個 JVM 程式。
列舉一些常用引數:
可選項 | 作用 |
---|---|
-l | 輸出完全的包名,應用主類名,jar的完全路徑名。 |
-q | 僅輸出 VM 識別符號,不包括 classname , jar name , arguments in main method 。 |
-m | 輸出 main method 的引數。 |
-v | 輸出 JVM 引數。 |
3. jstat: 虛擬機器統計資訊監視工具
jstat(JVM Statistics Monitoring Tool) 是用於監視虛擬機器各種執行狀態資訊的命令列工具。
位於 JDK 的 bin 目錄下,主要利用 JVM 內建的指令對 Java 應用程式的資源和效能進行實時的命令列的監控,包括了對 Heap size 和垃圾回收狀況的監控。
jstat 工具特別強大,有眾多的可選項,詳細檢視堆內各個部分的使用量,以及載入類的數量。使用時,需加上檢視程式的程式 id ,和所選引數。參考格式如下:
jstat -options
可以列出當前 JVM 版本支援的選項,常見的有:
- -class (類載入器)
- -compiler (JIT)
- -gc (GC堆狀態)
- -gccapacity (各區大小)
- -gccause (最近一次GC統計和原因)
- -gcnew (新區統計)
- -gcnewcapacity (新區大小)
- -gcold (老區統計)
- -gcoldcapacity (老區大小)
- -gcpermcapacity (永久區大小)
- -gcutil (GC統計彙總)
- -printcompilation (HotSpot編譯統計)
比如我想檢視一下我本地的 IDEA 程式的 GC 情況彙總,可以使用命令:
PS D:\> jstat -gcutil 5200
S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT
0.00 43.29 20.83 0.08 97.05 93.67 1 0.003 0 0.000 - - 0.003
查詢結果表明:
我的 IDEA 的新生代 Eden 區( E ,表示 Eden )使用了 20.83% 的空間, 2 個 Survivor 區( S0 、 S1 ,表示 Survivor0 、 Survivor1 ),S0 是空的,而 S1 使用了 43.29% ,老年代( O ,表示 Old )使用了 0.08% 的空間,元空間( M , 表示 Metaspace )使用了 97.05% 的空間。
程式執行以來共發生 Minor GC ( YGC ,表示 Young GC ) 1 次,總耗時 0.003 秒,發生 Full GC ( FGC ,表示 Full GC )0 次,總耗時( FGCT ,表示 Full GC Time )為 0 秒,所有 GC 總耗時( GCT ,表示 GC Time )為 0.003 秒。
4. jinfo: Java 配置資訊工具
jinfo(Configuration Info for Java)可以用來檢視正在執行的 Java 應用程式的擴充套件引數,包括 Java System 屬性和 JVM 命令列引數;也可以動態的修改正在執行的 JVM 一些引數。當系統崩潰時, jinfo 可以從 core 檔案裡面知道崩潰的 Java 應用程式的配置資訊。
使用 jps 命令的 -v 引數可以檢視虛擬機器啟動時顯式指定的引數列表,但如果想知道未被顯式指定的引數的系統預設值,除了去找資料外,就只能使用 jinfo 的 -flag 選項進行查詢了。
jinfo 命令格式:
jinfo [option] pid
查詢樣例:
PS D:\> jinfo -flags 5200
VM Flags:
-XX:CICompilerCount=4 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=734003200 -XX:MaxNewSize=244318208 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=89128960 -XX:OldSize=179306496 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
5. jmap: Java 記憶體映像工具
jmap(Memory Map for Java)命令用於生成堆轉儲快照(一般稱為 heapdump 或 dump 檔案)。
它也可以檢視堆內物件示例的統計資訊、檢視 ClassLoader 的資訊以及 finalizer 佇列。
jmap 命令格式:
jinfo [option] pid
option 可選的引數:
- no option: 檢視程式的記憶體映像資訊,類似 Solaris pmap 命令。
- heap: 顯示 Java 堆詳細資訊
- histo[:live]: 顯示堆中物件的統計資訊
- clstats:列印類載入器資訊
- finalizerinfo: 顯示在 F-Queue 佇列等待 Finalizer 執行緒執行 finalizer 方法的物件
- dump:
:生成堆轉儲快照 - F: 當 -dump 沒有響應時,使用 -dump 或者 -histo 引數. 在這個模式下, live 子引數無效.
- help:列印幫助資訊
- J
:指定傳遞給執行 jmap 的 JVM 的引數
PS D:\> jmap -dump:format=b,file=idea.bin 5200
Dumping heap to D:\idea.bin ...
Heap dump file created
6. jhat: 虛擬機器堆轉儲快照分析工具
JDK 提供jhat(JVM Heap Analysis Tool)命令與 jmap 搭配使用,來分析 jmap 生成的堆轉儲快照。 jhat 內建了一個微型的 HTTP/Web 伺服器,生成堆轉儲快照的分析結果後,可以在瀏覽器中檢視。
使用命令為:
PS D:\> jhat idea.bin
Reading from idea.bin...
Dump file created Thu Oct 08 18:54:37 CST 2020
Snapshot read, resolving...
Resolving 147921 objects...
Chasing references, expect 29 dots.............................
Eliminating duplicate references.............................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
然後在瀏覽器上訪問地址 http://localhost:7000/ 可以看到分析結果,不過這個分析工具一般沒什麼人會用,因為功能太過簡陋了。
相比較而言,我們可以使用 VisualVM 或者 Eclipse Memory Analyzer 再或者 IBM HeapAnalyzer 等工具分析剛才 jmap 產生的 dump 檔案。
7. jstack: Java 堆疊跟蹤工具
jstack(Stack Trace for Java)命令用於生成虛擬機器當前時刻的執行緒快照(一般稱為 threaddump 或者 javacore 檔案)。
執行緒快照就是當前虛擬機器內每一條執行緒正在執行的方法堆疊的集合,生成執行緒快照的目的通常是定位執行緒出現長時間停頓的原因,如執行緒間死鎖、死迴圈、請求外部資源導致的長時間掛起等,都是導致執行緒長時間停頓的常見原因。
jstack 命令格式:
jstack [option] pid
option 的可選引數:
- -F: 當正常輸出的請求不被響應時,強制輸出執行緒堆疊。
- -l: 除堆疊外,顯示關於鎖的附加資訊。
- -m: 如果呼叫到本地方法的話,可以顯示 C/C++ 的堆疊。
PS D:\> jstack -l 5200
2020-10-08 19:03:39
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.221-b11 mixed mode):
"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x00000000037b8000 nid=0x3f20 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None