程式扎記: [ JVM 應用 ] JVM 性能監控與故障處理工具 - JDK 命令列工具

標籤

2012年7月2日 星期一

[ JVM 應用 ] JVM 性能監控與故障處理工具 - JDK 命令列工具


前言 :
這邊要介紹的工具是基於 Windows 平台下 JDK 1.6 Update21, 如果 JDK 版本或作業系統不同, 工具所支援的功能可能會有差別. 底下為這些工具的簡介 :

(上述工具都在 %JAVA_HOME%/bin 下可以找得到)

jps - JVM 進程查詢工具 :
JDK 很多小工具的名稱都參考了 Unix 命令的命名方式, jps (JVM Process Status Tool) 是一個典型範例. 它的功能與 ps 命令類似 : 可以列出正在執行的 JVM 進程, 並顯示 JVM 執行主類別 (Main class, main() 函數所在類別) 的名稱, 以及這些進程本身 JVM 的唯一 ID (LVMID, Local Virtual Machine Identifier). 雖然功能單一, 但是它是其它工具使用頻率最高的 JDK 命令列工具. 對 JVM 來說, LVMID 與作業系統的進程 ID (PID, Process Identifier) 是一致的. 其命令列格式如下 :
jps [options] [hostid] 
參數 :
-q : 只輸出 LVMID, 省略主類的名稱
-m : 輸出 JVM 進程啟動時傳遞給主類別 main() 函數的參數.
-l : 輸出主類別全名, 如果進程執行的是 Jar 包, 輸出 Jar 路徑.
-v : 輸出 JVM 啟動時 JVM 參數

底下為其執行範例 :


jstat - JVM 統計資訊監視工具 :
jstat (JVM Statistic Monitoring Tool) 是用於監視 JVM 各種執行狀態資訊的命令列工具. 它可以顯示本地或遠端 JVM 進程中類別載入, 記憶體, 垃圾收集, JIT 編譯等執行資料, 在沒有 GUI 圖形介面只提供文件介面環境的伺服器上, 它將是執行時期定位 JVM 性能問題的首選工具. 其命令列格式為 :
jstat [option vmid [interval[s|ms] [count]]]

對於命令格式中的 VMID, 如果是本地 JVM 進程, VMID 與 LVMID 是一致的, 如果是遠端 JVM 進程, 那 VMID 的格式會是 :
[protocol:][//]lvmid[@hostname[:port]/servername]

參數 interval 和 count 代表查詢間隔與次數, 如果省略這兩個參數, 說明只查詢一次. 假設要每 250 毫秒查詢一次進程 2777 垃圾收集的狀況, 一共查詢 20 次, 命令會是 :
jstat -gc 2777 250 20

選項 option 代表使用者希望查詢的 JVM 資訊, 主要為三類 : 類別載入, 垃圾收集和執行時期編譯狀況, 具體選項參考下表 :


一個簡單執行範例如下 :


上面執行結果個欄位說明 :
E : Eden
S0, S1 : Survivor0, Survivor1
O : Old
P : Permanent
YGC : Young GC
YGCT : Young GC Time
FGC : Full GC
FGCT : Full GC Time
GCT : GC Time

jinfo - Java 設定資訊工具 :
jinfo (Configuration Info for Java) 的作用是即時的查看 JVM 使用的各項參數. 使用 jps 命令的 -v 參數可以查看 JVM 啟動時 "顯式" 指定的參數列表, 但如果想知道未被 "顯式" 指定的參數的系統預設值, 查了找資料就只能利用 jinfo 的 -flag 選項進行查詢. (如果是 JDK 1.6 以上, 也可以使用 java -XX:PrintFlagsFinal 查看參數預設值). jinfo 還可以使用 -sysprops 選項把 JVM 進程中的System.getProperties() 的內容列印出來. 不同的平台功能略有不同, 在 JDK 1.6 中 jinfo 對於 Windows 平台功能只提供了最基本的 -flag 選項. 其命令格式如下 :
jinfo [option] pid

下面為執行範例 : 查詢 SurvivorRatio 參數值


jmap - Java 記憶體 dump 工具 :
jmap (Memory Map for Java) 命令用於產生 Heap 快照 (一般稱 heapdump 或 dump 文件). 而 jmap 的作用不僅可以獲取 dump 檔, 它還可以查詢 finalize 執行佇列, Java Heap 與 永久代的詳細資訊. 另外如空間使用率, 當前用的是何種收集器等也可以查詢.

和 jinfo 命令一樣, jmap 有不少功能在 Windows 平台都是受限的, 除了生產 dump 檔的 -dump 選項和用於查看每個類別的實例, 空間占用統計的 -histo 選項所有操作系統都提供外, 其餘選項都只能在 Linux/Solaris 下使用. 其命令格式如下 :
jmap [option] vmid

option 選項的合法值與具體意義如下表 :


底下為執行範例 :


jhat - JVM Heap dump 快照分析工具 :
JDK 提供 jhat (JVM Heap Analysis Tool) 命令與 jmap 搭配使用, 來分析產出的 Heap 快照. jhat 內建一個微型的 HTTP/HTML 伺服器, 產生 dump 檔的分析結果後, 可以在瀏覽器上查看. 底下範圍為使用 jhat 將前面 jmap 導出的 Heap dump 進行分析 :
1. 執行命令 jhat <dump_path>


2. 接著可以使用瀏覽器檢視 dump 內容 :


jstack - Java 堆疊跟蹤工具 :
jstack (Stack Track for Java) 命令用於產生 JVM 當前時刻的 Threads 快照 (一般稱為 threaddump 或是 javacore 檔). Threads 快照就是當前 JVM 內每一條 Thread 正在執行的方法堆疊的集合, 產生 Threads 快照的主要目的是定位 Threads 出現長時間停頓的原因, 如 Threads 間 deadlock, 閉環, 請求外部資源導致長時間等待都是導致 Threads 長時間停頓的常見原因. Threads 出現停頓的時候透過 jstack 來查看各個 Threads 的呼叫堆疊, 就可以知道沒有回應的現成到底在做些什麼事情, 或者等待什麼資源. 命令格式如下 :
jstack [option] vmid

option 選項的合法值與說明如下表 :


接下來看看下面代碼, 建立兩個 Threads 並造成 dead lock :
  1. package ch03;  
  2.   
  3. public class Deadlock {  
  4.     static class Friend {  
  5.         private final String name;  
  6.   
  7.         public Friend(String name) {  
  8.             this.name = name;  
  9.         }  
  10.   
  11.         public String getName() {  
  12.             return this.name;  
  13.         }  
  14.   
  15.         public synchronized void bow(Friend bower) {  
  16.             System.out.format("\t[Info] %s: %s" + "  has bowed to me!%n"this.name, bower.getName());  
  17.             bower.bowBack(this);  
  18.         }  
  19.   
  20.         public synchronized void bowBack(Friend bower) {  
  21.             System.out.format("\t[Info] %s: %s" + " has bowed back to me!%n"this.name, bower.getName());  
  22.         }  
  23.     }  
  24.   
  25.     /** 
  26.      * Goal : Caused a deadlock Source : 
  27.      * http://docs.oracle.com/javase/tutorial/essential 
  28.      * /concurrency/deadlock.html 
  29.      *  
  30.      * @param args 
  31.      */  
  32.     public static void main(String[] args) {  
  33.         final Friend alphonse = new Friend("Alphonse");  
  34.         final Friend gaston = new Friend("Gaston");  
  35.         new Thread(new Runnable() {     // Thread1  
  36.             public void run() {  
  37.                 alphonse.bow(gaston);  
  38.             }  
  39.         }).start();  
  40.         new Thread(new Runnable() {     // Thread2  
  41.             public void run() {  
  42.                 gaston.bow(alphonse);  
  43.             }  
  44.         }).start();  
  45.     }  
  46. }  
其原理如下圖所示 :


執行範例如下 :

This message was edited 36 times. Last update was at 02/07/2012 22:12:14

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!