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 虛擬機》第三版