Java 故障處理工具

jps

JVM Process Status Tool,虛擬機進程狀況工具。

除了名字像 UNIX 的 ps 命令之外,它的功能也和 ps 命令類似:可以列出正在運行的虛擬機進程,並顯示虛擬機執行主類 (Main Class,main() 函數所在的類) 名稱以及這些進程的本地虛擬機唯一 ID (LVMID,Local Virtual Machine Identifier)。其他的 JDK 工具大多需要輸入它查詢到的 LVMID 來確定要監控的是哪一個虛擬機進程。

對於本地虛擬機進程來說,LVMID 與操作系統的進程 ID(PID,Process Identifier)是一致的,使用 Windows 的任務管理器或者 UNIX的 ps 命令也可以查詢到虛擬機進程的LVMID,但如果同時啓動了多個虛擬機進程,無法根據進程名稱定位時,那就必須依賴 jps 命令顯示主類的功能才能區分了。

命令格式:

jps [options] [hostid]

常用選項:

選項 作用
-q 只輸出 LVMID,省略主類的名稱
-m 輸出虛擬機進程啓動時傳遞給主類 main() 函數的參數
-l 輸出主類的全名,如果進程執行的是 JAR 包,則輸出 JAR 路徑
-v 輸出虛擬機進程啓動時的 JVM 參數

執行樣例:

jps -l
2388 D:\Develop\glassfish\bin\..\modules\admin-cli.jar
2764 com.sun.enterprise.glassfish.bootstrap.ASMain
3788 sun.tools.jps.Jps

jps 還可以通過 RMI (Remote Method Invocation, 遠程方法調用) 協議查詢開啓了 RMI 服務的遠程虛擬機進程狀態,參數 hostid 爲 RMI 註冊表中註冊的主機名。

jstat

JVM Statistics Monitoring Tool,虛擬機統計信息監視工具。

用於監視虛擬機各種運行狀態信息的命令行工具。它可以顯示本地或者遠程虛擬機進程中的類加載、內存、垃圾收集、即時編譯等運行時數據,在沒有 GUI 圖形界面、只提供了純文本控制檯環境的服務器上,它將是運行期定位虛擬機性能問題的常用工具。

命令格式:

jstat [option vmid [interval[s|ms] [count]]]

如果是本地虛擬機進程,VMID 與 LVMID 是一致的;

如果是遠程虛擬機進程,那 VMID 的格式應當是:

[protocol:][//]lvmid[@hostname[:port]/servername]

參數 interval 和 count 代表查詢間隔和次數,如果省略這 2 個參數,說明只查詢一次。

假設需要每 250 毫秒查詢一次進程 2764 垃圾收集狀況,一共查詢 20 次,那命令應當是:

jstat -gc 2764 250 20

選項 option 代表用戶希望查詢的虛擬機信息,主要分爲三類:類加載、垃圾收集、運行期編譯狀
況。

在這裏插入圖片描述

執行樣例:

jstat -gcutil 2764
S0   S1   E    O     P     YGC YGCT  FGC FGCT   GCT
0.00 0.00 6.20 41.42 47.20 16  0.105 3   0.472  0.577

查詢結果表明:這臺服務器的新生代 Eden 區(E,表示Eden)使用了 6.2% 的空間,2 個 Survivor 區(S0、S1,表示Survivor0、Survivor1)裏面都是空的,老年代(O,表示Old)和永久代(P,表示 Permanent)則分別使用了 41.42% 和 47.20% 的空間。程序運行以來共發生 Minor GC(YGC,表示Young GC)16次,總耗時0.105秒;發生 Full GC(FGC,表示Full GC)3次,總耗時(FGCT,表示Full GC Time)爲0.472秒;所有GC總耗時(GCT,表示GC Time)爲 0.577 秒。

jinfo

Configuration Info for Java,Java 配置信息工具。

作用是實時查看和調整虛擬機各項參數。使用 jps 命令的 -v 參數可以查看虛擬機啓動時顯式指定的參數列表,但如果想知道未被顯式指定的參數的系統默認值,除了去找資料外,就只能使用 jinfo 的 -flag 選項進行查詢了(如果只限於 JDK 6 或以上版本的話,使用 java-XX:+PrintFlagsFinal查看參數默認值也是一個很好的選擇)。

jinfo 還可以使用 -sysprops 選項把虛擬機進程的System.getProperties()的內容打印出來。這個命令在 JDK 5 時期已經隨着 Linux 版的 JDK 發佈,當時只提供了信息查詢的功能,JDK 6 之後,jinfo 在 Windows 和 Linux 平臺都有提供,並且加入了在運行期修改部分參數值的能力(可以使用-flag[+|-]name 或者 -flag name=value 在運行期修改一部分運行期可寫的虛擬機參數值)。在 JDK 6 中,jinfo 對於Windows 平臺功能仍然有較大限制,只提供了最基本的-flag選項。

命令格式:

jinfo [option] pid

執行樣例:

查詢 CMSInitiatingOccupancyFraction 參數值。

jinfo -flag CMSInitiatingOccupancyFraction 1444
-XX:CMSInitiatingOccupancyFraction=85

jmap

Memory Map for Java,Java 內存映像工具。用於生成堆轉儲快照(一般稱爲 heapdump 或 dump 文件)。

如果不使用 jmap 命令,要想獲取 Java 堆轉儲快照也還有一些比較“暴力”的手段:

  • -XX:+HeapDumpOnOutOfMemoryError 參數,可以讓虛擬機在內存溢出異常出現之後自動生成堆轉儲快照文件。
  • -XX:+HeapDumpOnCtrlBreak 參數則可以使用 [Ctrl]+[Break] 鍵讓虛擬機生成堆轉儲快照文件。
  • 在Linux系統下通過 Kill -3 命令發送進程退出信號“恐嚇”一下虛擬機,也能順利拿到堆轉儲快照。

jmap 的作用並不僅僅是爲了獲取堆轉儲快照,它還可以查詢 finalize 執行隊列、Java 堆和方法區的詳細信息,如空間使用率、當前用的是哪種收集器等。

和 jinfo 命令一樣,jmap 有部分功能在 Windows 平臺下是受限的,除了生成堆轉儲快照的 -dump 選項和用於查看每個類的實例、空間佔用統計的 -histo 選項在所有操作系統中都可以使用之外,其餘選項都只能在 Linux/Solaris 中使用。

命令格式:

jmap [option] vmid

option選項的合法值與具體含義如表所示:

在這裏插入圖片描述

執行樣例:

使用 jmap 生成一個正在運行的 Eclipse 的堆轉儲快照文件,例子中的 3500 是通過 jps 命令查詢到的 LVMID。

jmap -dump:format=b,file=eclipse.bin 3500
Dumping heap to C:\Users\IcyFenix\eclipse.bin ...
Heap dump file created

jhat

JVM Heap Analysis Tool,虛擬機堆轉儲快照分析工具。

JDK 提供 jhat 命令與 jmap 搭配使用,來分析 jmap 生成的堆轉儲快照。jhat 內置了一個微型的 HTTP / Web 服務器,生成堆轉儲快照的分析結果後,可以在瀏覽器中查看。

實事求是地說,在實際工作中,除非手上真的沒有別的工具可用,否則多數人是不會直接使用 jhat 命令來分析堆轉儲快照文件的,主要原因有兩個方面。一是一般不會在部署應用程序的服務器上直接分析堆轉儲快照,即使可以這樣做,也會盡量將堆轉儲快照文件複製到其他機器上進行分析,因爲分析工作是一個耗時而且極爲耗費硬件資源的過程,既然都要在其他機器上進行,就沒有必要再受命令行工具的限制了。另外一個原因是 jhat 的分析功能相對來說比較簡陋,VisualVM,以及專業用於分析堆轉儲快照文件的 Eclipse Memory Analyzer、IBM HeapAnalyzer 等工具,都能實現比 jhat 更強大專業的分析功能。

執行樣例:使用 jhat 分析上一節採用 jmap 生成的 Eclipse IDE 的內存快照文件。

jhat eclipse.bin
Reading from eclipse.bin...
Dump file created Fri Nov 19 22:07:21 CST 2010
Snapshot read, resolving...
Resolving 1225951 objects...
Chasing references, expect 245 dots....
Eliminating duplicate references...
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

屏幕顯示“Server is ready.”的提示後,用戶在瀏覽器中輸入http://localhost:7000/可以看到分析結果。

分析結果默認以包爲單位進行分組顯示,分析內存泄漏問題主要會使用到其中的 “HeapHistogram” (與jmap -histo功能一樣) 與 OQL 頁籤的功能,前者可以找到內存中總容量最大的對象,後者是標準的對象查詢語言,使用類似 SQL 的語法對內存中的對象進行查詢統計。

jstack

Stack Trace for Java,Java堆棧跟蹤工具。

用於生成虛擬機當前時刻的線程快照(一般稱爲 threaddump 或者 javacore 文件)。線程快照就是當前虛擬機內每一條線程正在執行的方法堆棧的集合,生成線程快照的目的通常是定位線程出現長時間停頓的原因,如線程間死鎖、死循環、請求外部資源導致的長時間掛起等,都是導致線程長時間停頓的常見原因。線程出現停頓時通過 jstack 來查看各個線程的調用堆棧,就可以獲知沒有響應的線程到底在後臺做些什麼事情,或者等待着什麼資源。

命令格式:

jstack [option] vmid

option 選項的合法值與具體含義如下所示:

選項 作用
-F 當正常輸出的請求不被響應時,強制輸出線程堆棧
-l 除堆棧外,顯示關於鎖的附加信息
-m 如果調用到本地方法的話,可以顯示 C / C++ 的堆棧

從 JDK 5 起,java.lang.Thread 類新增了一個 getAllStackTraces() 方法用於獲取虛擬機中所有線程的 StackTraceElement 對象。使用這個方法可以通過簡單的幾行代碼完成 jstack 的大部分功能,在實際項目中不妨調用這個方法做個管理員頁面,可以隨時使用瀏覽器來查看線程堆棧。

參考
《深入理解 Java 虛擬機》第三版

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章