給一個系統定位問題的時候,知識、經驗是關鍵基礎,數據是依據,工具是運用知識處理數據的手段。在定位JVM問題時,所依賴的數據主要包括異常堆棧、虛擬機運行日誌、垃圾收集器日誌、線程快照(threaddump.javacore文件)、堆轉儲快照(heapdump.hprof文件)。我們在學習工具之前應該意識到,工具都是知識技能的一層包裝,沒有什麼工具是萬能的,能夠「包治百病」。
在JDK的bin目錄下提供了編譯、運行、打包、部署、籤名、調試、監控、運維等各種命令行工具,這些命令行工具體積都非常小,MAC版本的JDK11下可以看到大部分都在49K左右,並非JDK團隊刻意把他們製作的如此精煉、統一,而是因為這些命令行工具大多僅是一層薄包裝而已,真正的功能代碼是實現在JDK的工具類庫中。
以下列出定位虛擬機性能相關的工具,JDK的其餘工具詳情見官網。
jps:JVM Process Status Tool 虛擬機進程狀況工具jps與Linux的ps命令類似,可以列出正在運行的虛擬機進程,並顯示虛擬機執行主類名稱以及這些進程的本地虛擬機唯一ID。
jps命令格式: jps [ options ] [ hostid]
jps執行樣例:
jps還可以通過RMI協議查詢開啟了RMI服務的遠程虛擬機進程狀態,參數hostid為RMI註冊表中註冊的主機名,命令格式為jps -m rmi://remotehost:8899(埠自定義)。
jps工具主要選項:
選項
作用
-q
只輸出LVMID,省略主類的名稱
-m
輸出虛擬機進程啟動時傳遞給主類main()函數的參數
-l
輸出主類的全名,如果進程執行的是JAR包,則輸出JAR路徑
-v
輸出虛擬機進程啟動時的JVM參數
jstat:JVM Statistics Monitoring Tool 虛擬機統計信息監控工具jstat是用於監視虛擬機各種運行狀態信息的命令行工具。它可以顯示本地或者遠程虛擬機進程中的類加載、內存、垃圾收集、即時編譯等運行時數據,在沒有GUI圖形界面、只提供了純文本控制臺環境的伺服器上,它將是運行期定位虛擬機性能問題的常用工具。
jstat命令格式:jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
參數interval和count代表查詢間隔和次數,如果省略只查詢一次當前數據。
jstat執行樣例:每250ms查一次49796進程的GC回收情況,共查20次。
jstat工具主要選項:
選項
作用
-class
監視類加載、卸載數量、總空間以及類裝載所耗費的時間
-gc
監視Java堆情況,包括Eden區、2個Survivor區、老年代、永久代等容量,已用空間,垃圾收集時間合計等信息
-gccapacity
監視內容與-gc基本相同,但輸出主要關注Java堆各個區域使用到的最大、最小空間
-gcutil
監視內容與-gc基本相同,但輸出主要關注已使用空間佔總空間的百分比
-gccause
與-gcutil功能一樣,但是會額外輸出導致上一次垃圾收集產生的原因
-gcnew
監視新生代垃圾收集狀況
-gcnewcapacity
監視內容與-gcnew基本相同,輸出主要關注使用到的最大、最小空間
-gcold
監視老年代垃圾收集狀況
-gcoldcapacity
監視內容與-gcold基本相同,輸出主要關注使用到的最大、最小空間
-gcpermcapacity
輸出永久代使用到的最大、最小空間
-compiler
輸出即時編譯器編譯過的方法、耗時等信息
-printcompilation
輸出已經被即時編譯的方法
Loaded
加載類的數量
Bytes
加載的KB數
Unloaded
卸載的類數量
Bytes
卸載的KB數
Time
執行類加載和卸載操作所花費的時間
Compiled
執行的編譯任務數量
Failed
執行失敗的編譯任務數量
Invalid
無效的編譯任務數量
Time
執行編譯任務所消耗的時間
FailedType
上次編譯失敗的編譯類型
FailedMethod
上次編譯失敗的類名和方法
jstat -printcompilation 50335Compiled
最近編譯的方法執行的編譯任務數。
Size
最近編譯的方法的字節碼的字節數。
Type
最新編譯方法的編譯類型。
Method
表示最近編譯的方法的類名和方法名
S0C
年輕代中第一個survivor(倖存區)的容量 (KB),即s0容量。
S1C
年輕代中第二個survivor(倖存區)的容量 (KB),即s1容量。
SOU
當前使用的s0容量大小(KB)
S1U
當前使用的s1容量大小(KB)
EC
年輕代中Eden(伊甸園)的容量 (KB)
EU
當前使用的Eden區容量大小(KB)
OC
老年代空間容量(KB)
OU
當前使用的老年代容量大小(KB)
PC
永久代容量(KB)
PU
當前使用的永久代大小(KB)
MC
元空間容量(KB)
MU
當前使用的元空間大小(KB)
CCSC
壓縮類容量(KB)
CCSU
當前使用的壓縮類大小(KB)
YGC
年輕代垃圾回收總次數
YGCT
年輕代來及回收總耗時
FGC
Full GC回收次數
FGCT
Full GC回收總耗時
CGC
並發GC階段STW的次數
CGCT
並發GC階段STW的總耗時
GCT
垃圾回收總耗時
NGCMN
年輕代最小值
NGCMX
年輕代最大值
NGC
當前年輕代使用容量
SOC
當前s0區容量
S1C
當前s1區容量
EC
當前Eden區容量
OGCMN
老年代最小值
OGCMX
老年代最大值
OGC
當前老年代使用容量
OC
老年代空間
MCMN
元空間最小值
MCMX
元空間最大值
MC
元空間容量
CCSMN
壓縮類空間最小容量
CCSCMX
壓縮類空間最大容量
CCSC
壓縮的類提交大小
YGC
年輕代GC數量
FGC
Full GC數量
CGC
並發GC階段STW的次數S0C
當前s0區大小
S1C
當前s1區大小
S0U
s0使用大小
S1U
s1使用大小
TT
對象在新生代存活的次數
MTT
對象在新生代存活的最大次數
DSS
期望的倖存區大小
EC
當前Eden區大小
EU
Eden區使用大小
YGC
ygc次數
YGCT
ygc耗時
jstat -gcnewcapacity 18719NGCMN
最小年輕代容量
NGCMX
最大年輕代容量
NGC
當前年輕代使用容量
S0CMX
s0最大容量
S0C
當前s0使用容量
S1CMX
s1最大容量
S1C
當前s1使用容量
ECMX
Eden區最大容量
EC
當前Eden區使用容量
YGC
年輕代gc次數
FGC
fgc次數
CGC
並發GC階段STW的次數MC
元空間大小
MU
當前使用元空間大小
CCSC
壓縮類空間大小
CCSU
使用壓縮類空間大小
OC
老年代空間大小
OU
老年代使用大小
YGC
ygc次數
FGC
full gc次數
FGCT
full gc 總耗時
CGC
並發標記STW次數
CGCT
並發標記STW耗時
GCT
垃圾回收總耗時
jstat -gcoldcapacity 18719OGCMN
老年代最小容量
OGCMX
老年代最大容量
OGC
當前使用老年代容量
OC
老年代空間
YGC
ygc 次數
FGC
full gc次數
FGCT
full gc 總耗時
CGC
並發標記STW次數CGCT
並發標記STW耗時
GCT
垃圾回收總耗時
S0
so利用率佔空間當前容量的百分比。
S1
s1利用率佔空間當前容量的百分比。
E
Eden空間利用率佔空間當前容量的百分比。O
老年代利用率佔空間當前容量的百分比。M
元空間利用率佔空間當前容量的百分比。CCS
壓縮的類空間利用率(以百分比表示)
YGC
ygc 次數
YGCT
ygc總耗時
FGC
full gc次數
FGCT
full gc 總耗時
CGC
並發標記STW次數CGCT
並發標記STW耗時
GCT
垃圾回收總耗時
S0
so利用率佔空間當前容量的百分比。
S1
s1利用率佔空間當前容量的百分比。
E
Eden空間利用率佔空間當前容量的百分比。O
老年代利用率佔空間當前容量的百分比。M
元空間利用率佔空間當前容量的百分比。CCS
壓縮的類空間利用率(以百分比表示)
YGC
ygc 次數
YGCT
ygc總耗時
FGC
full gc次數
FGCT
full gc 總耗時
CGC
並發標記STW次數CGCT
並發標記STW耗時
GCT
垃圾回收總耗時
LGCC
上次垃圾收集的原因
GCC
當前垃圾收集的原因
jinfo:Configuration Info For Java 配置信息工具通過jinfo可以實時查看和調整虛擬機各項參數。如果不選擇options,默認將同時列印命令行標誌和系統屬性名稱/值對。
jinfo命令格式: jps [ options ] [ hostid]
jinfo執行樣例:
jinfo主要參數選項:
-flag name
列印指定命令行標誌的名稱和值。
-flag [+|-]name
啟用或禁用指定的布爾命令行標誌。
-flag name=value
將指定的命令行標誌設置為指定的值。
-flags
列印傳遞給JVM的命令行標誌。
-sysprops
將Java系統屬性列印為名稱/值對。
-h or -help
列印幫助信息
jmap:Memory Map for Java 內存映射工具jmap命令用於生產堆內存快照文件(heapdump或dump文件)。除獲取堆轉儲快照之外,它還可以查詢finalize執行隊列、Java堆和方法區的詳細信息,如空間使用率、當前使用的是哪些收集器等。
jmap命令格式:jmap [options] pid
jmap執行樣例:
jmap命令可選參數:
-dump
生產Java堆轉儲快照。格式為-dump:[live,]format=b,file=<filename>,其中live子參數說明是否只dump出存活的對象,不加live默認dump所有對象。format=b表示以hprof二進位格式列印。
-finalizerinfo
顯示在F-Queue中等待Finalizer線程執行finalize方法的對象。只在Linux/Solaris平臺下有效。
-heap
顯示Java堆的詳細信息,如使用哪種回收期、參數配置、分代狀況等。只在Linux/Solaris平臺下有效。
-hiso
顯示堆中對象統計信息,包括類、實例數量、合計容量。
-permstat
以ClassLoader為統計口徑顯示永久代內存狀態。只在Linux/Solaris平臺下有效。
-F
當虛擬機進程對-dump選項沒有響應時,可使用這個選項強制生成dump快照。只在Linux/Solaris平臺下有效。
jhat:JVM Heap Analysis Tool 虛擬機堆轉儲快照分析工具JDK提供jhat命令與jmap命令搭配使用,用來分析jmap生成的堆轉儲快照。jhat內置一個微型的HTTP/web伺服器,生成堆轉儲快照的分析結果後,可以再瀏覽器中查看。從JDK9以後Oracle已經移除了jhat。
-stack false/true
關閉跟蹤對象分配調用堆棧。如果堆轉儲中沒有分配站點信息,則必須將此標誌設置為false。默認為true。
-refs false/true
關閉對對象引用的跟蹤。默認為true。默認情況下,將為堆中的所有對象計算後向指針(指向給定對象的對象,也就是引用者或傳入引用)。
-port port-number
設置jhat的HTTP伺服器的埠。默認值為7000。
-exclude exclude-file
指定一個文件,該文件列出了應從「可達對象」查詢中排除的數據成員。例如,如果文件列出了java.lang.String.value,則無論何時計算從特定對象「 o」可訪問的對象列表,都將不考慮涉及java.lang.String.value欄位的引用路徑。
-baseline baseline-dump-file
指定基準堆轉儲。兩個堆轉儲中具有相同對象ID的對象將被標記為不是「新的」。其他對象將被標記為「新」。在比較兩個不同的堆轉儲時,這很有用。
-debug int
設置此工具的調試級別。0表示沒有調試輸出。為更多詳細模式設置較高的值。
-J<flag>
將<flag>傳遞到運行jhat的Java虛擬機。例如,-J-Xmx512m使用最大堆大小為512MB。
jstack:Stack Trace for Java 堆跟蹤工具jstack 命令用於生成虛擬機當前時刻的線程快照(一般稱為threaddump或者Javacore文件)。線程快照就是當前虛擬機每一條線程正在執行的方法堆棧的集合,生產線程快照的目的通常是定位線程出現長時間停頓的原因,如線程間死鎖、死循環、請求外部資源導致的長時間掛起等,都是導致線程長時間停頓的常見原因。線程出現停頓時通過jstack來查看各個線程的調用堆棧,就可以獲知沒有響應的線程到底在後臺做了些什麼事情,或者等待著什麼資源。
jstack命令格式:jstack [options] pid
jstack執行案例:
jstack可選參數:
-F
當正常輸出的請求不被響應時,強制輸出線程堆棧
-l
除堆棧外,顯示關於鎖的附加信息
-m
如果調用本地方法的話,可以顯示C/C++的堆棧
-e
列印線程的擴展信息
JDK中除了附帶大量的命令行工具外,還提供了幾個功能集成度更高的可視化工具,用戶可以使用這些可視化工具以更加便捷的方式進行進程故障診斷和調試工作。