本文部分摘自《深入理解 Java 虛擬機器第三版》
基礎故障處理工具
Java 開發人員肯定都知道 JDK 的 bin 目錄下有許多小工具,這些小工具除了用於編譯和執行 Java 程式外,打包、部署、簽名、除錯、監控、運維等各種場景都可能會見到它們的影子
本文主要介紹的是用於監視虛擬機器執行狀態和進行故障處理的工具,根據軟體可用性和授權的不同,可以分成三類:
- 商業授權工具:主要是 JMC(Java Mission Control)及它要使用到的 JFR(Java Flight Recorder)。JMC 在個人開發環境中使用是免費的,但在商業環境中使用則需付費
- 正式支援工具:這一類工具屬於長期被支援的工具
- 實驗性工具:這一類工具帶有實驗性質,日後可能會轉正,也可能會在某個 JDK 版本中無聲無息地消失
虛擬機器程式狀況工具
使用 jps(JVM Process Status Tool)可以列出正在執行的虛擬機器程式,並顯示虛擬機器執行主類(main 函式所在的類)名稱以及這些程式的本地虛擬機器唯一 ID(LVMID,Local Virtual Machine Identifier)
該命令可以獲取虛擬機器程式的 LVMID,從而定位想要監控的程式,而 LVMID 一般與作業系統的程式 ID 一致
jps [options] [hostid]
jps 也可以通過 RMI 協議查詢開啟了 RMI 服務的遠端 Java 虛擬機器程式狀態,引數 hostid 為 RMI 登錄檔中註冊的主機名
jps 的其他常用選項如表:
選項 | 作用 |
---|---|
-q | 只輸出 LVMID,省略主類的名稱 |
-m | 輸出虛擬機器程式啟動時傳遞給主類 main() 函式的引數 |
-l | 輸出主類的全名,如果程式執行的是 JAR 包,則輸出 |
-v | 輸出虛擬機器程式啟動時的 JVM 引數 |
虛擬機器統計資訊監視工具
jstat(JVM Statistics Monitoring Tool)是用於監視虛擬機器各種執行狀態資訊的命令列工具,可以顯示本地或者遠端虛擬機器程式中的類載入、記憶體、垃圾收集、即時編譯等執行時資料
jstat [ option vmid [interval[s|ms] [count]] ]
如果是本地虛擬機器程式,VMID 與 LVMID 是一致的;如果是遠端虛擬機器程式,那 VMID 的格式應當是
[protocaol:][//]lvmid[@hostname[:port]/servername]
引數 interval 和 count 代表查詢間隔和次數,如果省略這兩個引數,說明只查詢一次。假設需要每 250 毫秒查詢一次程式 2764 的垃圾收集情況,一共查詢 20 次,那命令應當是
jstat -gc 2764 250 20
選項 option 代表使用者希望查詢的虛擬機器資訊,主要分三類:類載入、垃圾收集、執行期編譯狀況等
選項 | 作用 |
---|---|
-class | 監視類載入、解除安裝數量、總空間以及類裝載所耗費的時間 |
-gc | 監視 Java 堆狀況,包括 Eden 區、兩個 Survivor 區、老年代、永久代等的容量、已用空間、垃圾收集時間合計等資訊 |
-gccapacity | 監視內容與 -gc 基本相同,但輸出主要關注 Java 堆各個區域使用到的最大、最小空間 |
-gcutil | 監視內容與 -gc 基本相同,但輸出主要關注已使用空間佔總空間的百分比 |
-gccause | 與 -gcutil 功能一樣,但會額外輸出導致上一次垃圾收集產生的原因 |
-gcnew | 監視新生代垃圾收集情況 |
-gcnewcapacity | 監視內容與 -gcnew 基本相同,但輸出主要關注使用到的最大、最小空間 |
-gcold | 監視老年代垃圾收集情況 |
-gcoldcapacity | 監視內容與 -gcold 基本相同,但輸出主要關注使用到的最大、最小空間 |
-gcpermcapacity | 輸出永久代使用到的最大、最小空間 |
-compiler | 輸出即時編譯器編譯過的方法、耗時等資訊 |
-printcompilation | 輸出已經被即時編譯的方法 |
Java 配置資訊工具
jinfo(Configuration Info for Java)的作用是實時檢視和調整虛擬機器各項引數,使用 jps 命令的 -v 引數可以檢視虛擬機器啟動時顯示指定的引數列表,獲取 pid
jinfo [option] pid
使用 -flag <name> 選項列印虛擬機器標記引數的值,name 表示虛擬機器標記引數的名稱
jinfo -flag PrintGC 21768
使用 -flag [+|-]<name> 選項可以開啟或關閉虛擬機器表示引數,+ 表示開啟,- 表示關閉
jinfo -flag +PrintGC 21768
jinfo -flag -PrintGC 21768
使用 -flag <name> = <value> 可以設定虛擬機器標記引數的值,但並不是每個引數都可以被動態修改
jinfo -flag HeapDumpPath=C:\error.hprof 21768
剩下的常用選項如表
選項 | 作用 |
---|---|
-flags | 列印虛擬機器引數,如 -XX:NewSize |
no option | 不帶任何選項時,會同時列印虛擬機器引數和系統引數 |
-sysprops | 列印系統引數 |
-h | -help | 列印幫助資訊 |
Java 記憶體對映工具
jmap(Memory Map for Java)命令用於生成堆轉儲快照,還可以查詢 finalize 執行佇列、Java 堆和方法區的詳細資訊,如空間使用率、當前用的是哪種收集器等
jmap [option] vmid
option 選項的合法值與具體含義
選項 | 作用 |
---|---|
-dump | 生成 Java 堆轉儲快照,格式為 -dump:[live,]format=b,file=<filename>,其中 live 子引數說明是否只 dump 出存活的物件 |
-finalizerinfo | 顯示在 F-Queue 中等待 Finalizer 執行緒執行 finalize 方法的物件 |
-heap | 顯示 Java 堆詳細資訊,如使用哪種回收期、引數配置、分代狀況 |
-histo | 顯示堆中物件統計資訊,包括類、例項數量、合計容量 |
-permstat | 以 ClassLoader 為統計口徑顯示永久代記憶體狀態 |
-F | 當虛擬機器程式對 -dump 選項沒有響應時,可使用該選項強制生成 dump 快照 |
虛擬機器堆轉儲快照分析工具
JDK 提供 jhat(JVM Heap Analysis Tool)命令和 jmap 搭配使用,用來分析 jmap 生成的堆轉儲快照。不過 jhat 的分析功能相等簡陋,一般會使用其他功能更強大的分析工具
jhat 內建一個簡單的 web 伺服器,此命令執行後,jhat 在命令列裡顯示分析結果的訪問地址,可以用 -port 選項指定埠
有時 dump 出來的堆很大,在啟動時會報堆空間不足的錯誤,可以使用如下引數
jhat -J-Xmx512m <heap dump file> # 這個記憶體大小可根據自己電腦進行設定
Java 堆疊跟蹤工具
jstack(Stack Trace for Java)命令用於生成虛擬機器當前時刻的執行緒快照(一般稱為 threaddump 或 javacore 檔案)。執行緒快照就是當前虛擬機器內每一條執行緒正在執行的方法堆疊的集合,生成執行緒快照的目的通常是定位執行緒出現長時間停頓的原因,如執行緒間死鎖、死迴圈、請求外部資源導致的長時間掛起等
jstack [option] vmid
option 選項的合法值與具體含義如表
選項 | 作用 |
---|---|
-F | 當正常輸出的請求不被響應時,強制輸出執行緒堆疊 |
-l | 除堆疊外,顯示關於鎖的附加資訊 |
-m | 如果呼叫到本地方法的話,可以顯示 C/C++ 的堆疊 |
從 JDK5 開始,java.lang.Thread 類新增了一個 getAllStackTraces() 方法用於獲取虛擬機器中所有執行緒的 StackTraceElement 物件,使用這個方法可以完成 jstack 的大部分功能,在實際專案中可以呼叫這個方法做一個管理員頁面,隨時使用瀏覽器來查閱執行緒堆疊