JDK命令列(jps、jstat、jinfo、jmap、jhat、jstack)與JConsole
javafirst 2018-12-14 11:30:00
作者:像風一樣i 來源:https://www.cnblogs.com/yueshutong/p/9812464.html
很多資料在介紹JDK命令列工具時並不是在Java8環境下,因此還在使用過時的永久區系列的引數,給一些讀者造成困難。
Java8使用Metaspace(元空間)代替永久區,對於64位平臺,為了壓縮JVM物件中的_klass指標的大小,引入了類指標壓縮空間(Compressed Class Pointer Space) 。關於這點,可以參考部落格https://blog.csdn.net/liang0000zai/article/details/51168095。
1. JDK命令列工具
在JDK的開發包中,除了大家熟知的java.exe和javac.exe外,還有一系列輔助工具。這些工具在JDk安裝目錄下的bin目錄中。如圖:
雖然乍看之下,這些工作都是exe的可執行檔案。但事實上,它們只是Java程式的一層包裝,其真正實現是在 tools.jar 中。
以jps工具為例,在控制檯執行jps命令和java -classpath %Java_HOME%/lib/tools.jar sun.tools.jps.Jps命令是等價的,即jps.exe只是這個命令的一層包裝。
在學習以下命令之前,不妨使用IDEA寫個不會退出的小程式,方便測試。示例程式碼:
package cn.zyzpp.jConsole; import java.text.SimpleDateFormat; import java.util.Date; public class Main { public static void main(String[] args) throws InterruptedException { while (true){ Thread.sleep(10000); //Byte[] bytes = new Byte[1024]; //bytes = null; //System.gc(); System.out.println(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date())); } } }
1.1 jps命令
命令jps用於列出java程序,直接執行jps不加任何引數,可以列出Java程式的程序ID以及Main函式等名稱。
從這個輸出中可以看到,當前系統中共存在4個Java應用程式,其中第一個輸出jps就是jps命令本身,這個更加證明此命令本質也是一個Java程式。此外,jps還提供了一系列引數來控制它的輸出內容。
引數-q指定jps只輸出程序ID,而不輸出類的短名稱:
引數-m用於輸出傳遞給Java程序(主函式)的引數:
引數 -l用於輸出主函式的完整路徑:
引數 -v可以顯示傳遞給JVM的引數:
1.2 jstat命令
jstat是一個可以用於觀察Java應用程式執行時資訊的工具。它的功能非常強大,可以通過它,檢視堆資訊的詳細使用情況。它的基本使用語法為:
jstat -<option> [-t] [-h<lines>] <vmid> [<interval>] [<count>]
選項option可以由以下值構成:
- -class:顯示ClassLoader的相關資訊。
- -compiler:顯示JIT編譯的相關資訊。
- -gc:顯示與GC相關的堆資訊。
- -gccapacity:顯示各個代的容量及使用情況。
- -gccause:顯示垃圾收集相關資訊(同-gcutil),同時顯示最後一次或當前正在發生的垃圾收集的誘發原因。
- -gcnew:顯示新生代資訊。
- -gcnewcapacity:顯示新生代大小與使用情況。
- -gcold:顯示老年代與永久代的資訊。
- -gcoldcapacity:顯示老年代的大小。
- -gcmetacapacity:顯示元空間的大小。(在java8之前是使用-gcpermcapacity顯示永久代的大小)
- -gcutil:顯示垃圾收集資訊。
- -printcompilation:輸出JIT編譯的方法資訊。
以上選項可以輸入 jstat -options 檢視。
-t 引數可以在輸出資訊前加一個 Timestamp 列,顯示程式的執行時間。
-h 引數可以在週期性資料輸出時,輸出多少行資料後,跟著輸出一個表頭資訊。
vmid 引數就是Java程序id。
interval 引數用於指定輸出統計資料的週期,單位為毫秒。
count 用於指定一共輸出多少次資料。
示例
1.2.1 -class
輸出java程序13516的ClassLoader相關資訊。每秒鐘統計一次資訊,一共輸出2次:
在-class的輸出中,Loaded 表示載入了類的數量,Bytes表示載入類的合計大小(KB),Unloaded 表示解除安裝類的數量,第2個Bytes表示解除安裝類的大小,Time表示在載入和解除安裝類上所花的時間。
1.2.2 -compiler
下例顯示了檢視JIT編譯的資訊:
Compiled 表示編譯任務執行的次數,Failed表示編譯失敗的次數,Invalid 表示編譯不可用的次數,Time 表示編譯後的總耗時,FailedType 表示最後一次編譯失敗的型別,FailedMethod 表示最後一次編譯失敗的類名和方法名。
1.2.3 -gc
下例顯示了與GC相關的堆資訊的輸出:
各項引數的含義如下:
- S0C:s0(from)的大小(KB)。
- S1C:s1(from)的大小(KB)。
- S0U:s0(from)已使用的空間(KB)。
- S1U:s1(from)已經使用的空間(KB)
- EC:eden區的大小(KB)
- EU:eden區已經使用的空間(KB)
- OC:老年代大小(KB)
- OU:老年代已經使用的空間(KB)
- MC:元空間的大小(Metaspace)(KB)
- MU:元空間已使用大小(KB)
- CCSC:壓縮類空間大小(compressed class space)(KB)
- CCSU:壓縮類空間已使用大小(KB)
- YGC:新生代gc次數
- YGCT:新生代gc耗時(秒)
- FGC:Full gc次數
- FGCT:Full gc耗時(秒)
- GCT:gc總耗時(秒)
1.2.4 -gccapacity
下例顯示了各個代的資訊,與-gc相比,它不僅輸出了各個代的當前大小,也包含了各個代的最大值和最小值。
各引數含義:
- NGCMN:新生代最小(初始化)容量(位元組)
- NGCMX:新生代最大容量(位元組)
- NGC:當前新生代容量(位元組)
- OGCMN:老年代最小容量(位元組)
- OGCMX:老年代最大容量(位元組)
- MCMN:metaspace(元空間)中初始化(最小)的大小 (位元組)
- MCMX :metaspace(元空間)的最大容量 (位元組)
- CCSMN:最小壓縮類空間大小(位元組)
- CCSMX:最大壓縮類空間大小(位元組)
1.2.5 -gccause
下列顯示了最近一次GC的原因以及當前GC的原因:
各項引數如下:
- LGCC:上次GC的原因。
- GCC:當前GC的原因。
1.2.6 -gcnew
-gcnew 引數用於檢視新生代的一些詳細資訊:
各項引數的含義如下:
- TT:新生代物件晉升到老年代物件的年齡。
- MTT:新生代物件晉升到老年代物件的年齡最大值。
- DSS:所需的survivor區大小。
1.2.7 -gcnewcapacity
-gcnewcapacity 引數可以詳細輸出新生代各個區的大小資訊:
各項引數的含義如下:
- S0CMX:s0區的最大值(KB)。
- S1CMX:s1區的最大值(KB)。
- ECMX:eden區的最大值(KB)。
1.2.8 -gcold
-gcold 可以用於展現老年代GC的概況。
1.2.9 -gcoldcapacity
-gcoldcapacity 用於展現老年代的容量資訊:
1.2.10 -gcmetacapacity與-gcpermcapacity
-gcpermcapacity 用於展示永久區的使用情況,但是在Java8環境下使用會報錯找不到。因為java8的永久區被元空間取而代之。所以要使用 -gcmetacapacity:
1.2.11 -gcutil
-gcutil 用於展示GC回收相關資訊:
各項引數如下:
- S0:s0區使用的百分比。
- S1:s1區使用的百分比。
- E:eden 區使用的百分比。
- O:old區使用的百分比。
- M:元空間使用的百分比。
- CCS:壓縮類空間使用的百分比。
1.3 jinfo命令
jinfo 可以用來檢視正在執行的Java執行程式的擴充套件引數,甚至支援在執行時修改部分引數。它的基本語法為:
jinfo <option> <pid>
其中option可以為以下資訊:
- -flag: 列印指定java虛擬機器的引數值。
- -flag [+|-]< name >:設定或取消指定java虛擬機器引數的布林值。
- -flag < name >=< value >:設定指定java虛擬機器的引數的值。
- 在很多情況下,Java應用程式不會指定所有的JVM引數。而此時,開發人員可能不知道某一個具體的JVM引數的預設值。有了 jinfo 工具,開發人員可以很方便地找到JVM引數的當前值。
1)下例顯示了新生代物件晉升到老年代物件的最大年齡。在應用程式執行時並沒有指定這個引數,但是通過jinfo,可以檢視這個引數的當前的值。
2)顯示是否列印GC詳細資訊。
3)修改部分引數的值,下面是對PrintGCDetails引數的修改。
1.4 jmap命令
jmap 可以生成Java應用程式的堆快照和物件的統計資訊。基本語法為:
jmap [option] vmid
option 選項如下:
下例使用jmap生成PID為9440的Java應用程式的物件統計資訊,並輸入到 s.txt 檔案中。
jmap -histo 9440 >c:s.txt
輸出檔案有如下結構:
可以看到,這個輸出顯示了記憶體中的例項數量和合計。
另一個更為重要的功能是得到Java程式的當前堆快照:
本例中,將應用程式的堆快照輸出到E盤的heap.bin檔案中。之後,可以通過多種工具分析檔案。比如,下文中提到的jhat工具。也可以使用 Visual VM工具開啟這個快照檔案。
1.5 jhat命令
使用 jhat 工具可以用於分析Java應用程式的堆快照內容。以前文中jmap的輸出對檔案 heap.hprof 為例:
jhat 在分析完成後,使用HTTP伺服器展示其分析結果。在瀏覽器中訪問http://localhost:7000/,結果如圖所示。
在預設頁中,jhat 伺服器顯示了所有的非平臺類資訊。單擊連結進入,可以檢視選中類的超類、ClassLoader 以及該類的例項等資訊。此外,在頁面底部,jhat還為開發人員提供了其他查詢方式(Other Queries)。
通過這些連結,開發者可以進一步檢視所有類資訊(包括Java平臺的類)。所有類的例項數量以及例項的具體資訊。最後,還有一個連結指向OQL查詢介面。
圖中顯示了在jhat中,檢視Java應用程式裡java.lang.String類的例項數量:
單擊 instances 連結可以進一步檢視 String 物件的例項,如圖所示:
通常,匯出的堆快照資訊可以非常大,由於資訊太多,可能很難通過頁面上簡單的連結索引找到想要的資訊。為此,jhat還支援使用OQL語句對堆快照進行查詢。執行 OQL 語言的介面非常簡潔,如圖所示。使用OQL查詢出當前Java程式中所有java.io.File物件的路徑。OQL如下:
select file.path.value.toString() from java.io.File file
1.6 jstack命令
jstack 可用於匯出Java應用程式的執行緒堆疊。語法為:
jstack [-l] <pid>
-l選項用於列印鎖的附加資訊。
jstack 工具會在控制檯輸出程式中所有的鎖資訊,可以使用重定向將輸出儲存到檔案,如:
jstack -l 16196 >edeadlock.txt
通過 jstack 工具不僅可以得到執行緒堆疊,它還能自動進行死鎖檢查,輸出找到的死鎖資訊。
1.7 jstatd命令
之前所述的工具中,只涉及到監控本機的Java應用程式。而在這些工具中,一些監控工具也支援對遠端計算機的監控(如:jps、jstat)。為了啟用遠端監控,則需要配合使用jstatd工具。
命令jstatd是一個RMI服務端程式,它的作用相當於代理伺服器,建立本地計算機與遠端監控工具的通訊。jstatd伺服器將本機的Java應用程式資訊傳遞到遠端計算機。
直接開啟jstatd伺服器可能會丟擲訪問拒絕異常:
這是由於jstatd程式沒有足夠的許可權所致,可以使用Java的安全策略,為其分配相應的許可權,下面程式碼為jststd分配了最大的許可權,將其儲存在jstatd.all.policy檔案中:
grant codebase "file:${java.home}/../lib/tools.jar" { permission java.security.AllPermission; };
然後,使用以下命令再次開啟jstatd伺服器:
jstatd -J-Djava.security.policy=c:jstatd.all.policy
伺服器即可開啟成功。
-J引數是一個公共的引數,如jps、jstat等命令都可以接受這個引數。由於jsp、jstat命令本身也是Java應用程式,-J引數可以為jps等命令本身設定其JVM引數。
預設情況下,jstatd 將在1099埠開啟RMI伺服器:
使用jps命令顯示遠端計算機的Java程序:
jps localhost:1099
使用jstat命令顯示遠端程序460的GC情況:
jstat -gcutil [email protected]:1099
1.8 hprof工具
hprof不是獨立的監控工具,它只是一個Java agent工具,它可以用於監控Java應用程式在執行時的CPU資訊和堆資訊。使用 java -agentlib:hprof=help 命令可以檢視hprof 的幫助文件。下面是 hropf 工具幫助資訊的輸出:
使用hprof工具可以檢視程式中各個函式的CPU佔用時間。以下程式碼包含3個方法,分別佔用不同的CPU時間:
public class HProfTest { public void slowMethod(){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } public void slowerMethod(){ try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } public void fastMethod(){ try { Thread.yield(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { HProfTest hProfTest = new HProfTest(); hProfTest.fastMethod(); hProfTest.slowMethod(); hProfTest.slowerMethod(); } }
使用引數-agentlib:hprof=cpu=times,interval=10執行以上程式碼。times選項將會在Java函式的呼叫前後記錄函式的執行時間,進而計算函式的執行時間。hprof=cpu是針對cpu統計時間。interval=10 取樣10次。程式執行後會發現多了一個文字檔案java.hprof.txt,開啟後檢視部分輸出如下,可以很容易看到執行時間最長的函式:
使用引數-agentlib:hprof=heap=dump,format=b,file=e:core.hprof 執行程式,可以將應用程式的堆快照儲存在指定檔案 e:core.hprof 中。使用MAT或者Visual VM等工具可以拆這個堆檔案。
使用引數 -agentlib:hprof=heap=sites 執行程式,可以輸出Java應用程式中各個類所佔的記憶體百分比,部分輸出如下:
2.JConsole工具
JConsole(Java Monitoring and ManagementConsole)工具時JDK自帶的圖形化效能監控工具。通過JConsole工具,可以檢視Java應用程式的執行概況,監控堆資訊、永久區使用情況、類載入情況等。本節主要介紹JConsole工具的基本使用方法。
2.1 JConsole連線Java程式
JConsole 程式在%JAVA_HOME%/bin目錄下,雙擊啟動後,程式便要求指定連線Java應用程式,如圖所示。
在羅列的本地Java應用程式選擇PID為15908的程式,連線。
如果需要使用JConsole連線遠端程序,則需要在遠端Java應用程式啟動時,加上如下引數:
-Djava.rmi.server.hostname=127.0.0.1 #遠端伺服器的ip地址 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8888 #指定jmx監聽的埠 -Dcom.sun.management.jmxremote.authenticate=false #是否開啟認證 -Dcom.sun.management.jmxremote.ssl=false #是否開啟ssl
基於以上配置啟動的Java應用程式,通過JConsole在遠端連線時,只需要填寫如下遠端程序即可:
127.0.0.1:8888
2.2 Java程式概況
在連線上Java應用程式後,便可以檢視應用程式概況。
2.3 記憶體監控
切換到記憶體監控頁面,JConsole 可以顯示當前記憶體的詳細資訊。這不僅是包括堆記憶體的整體資訊,更細化到eden區、survivior 區、老年代的使用情況。同時,也包括非堆區,即永久代的使用情況,如圖所示,單機介面右上角的“執行GC”按鈕,可以強制應用程式進行一次Full GC。
2.4 執行緒監控
JConsole 中的執行緒選項卡允許開發人員監控程式內的執行緒,如圖所示。JConsole 顯示了系統內的執行緒數量,並在螢幕下方,顯示了程式中所有的執行緒。單擊執行緒名稱,便可以檢視執行緒的棧資訊。
使用最下方的“監測死鎖”按鈕。還可以自動監測多執行緒應用程式的死鎖情況。
2.5 類載入情況
JConsole的類頁面如圖所示,顯示了系統以及裝載的類數量。在詳細資訊欄中,還顯示了已解除安裝的類數量。
2.6 虛擬機器資訊
在VM摘要頁面,JConsole 顯示了當前應用程式的執行環境。包括虛擬機器型別、版本、堆資訊以及虛擬機器引數等。
2.7 MBean管理
MBean頁面允許通過JConsole進行MBean的管理,包括檢視或者設定MBean的屬性、執行MBean的方法等。下圖是MBean的管理介面,這裡選中了Memory的Verbose屬性。通過修改Verbose的屬性值,可以在程式執行時動態開啟或者關閉GC的輸出資訊。
MBean種類繁多。主要的操作如下:
2.8 使用外掛
除了基本功能之外,JConsole還支援外掛擴充套件。在JDK的安裝目錄下,就有一個自帶的JConsole外掛。使用以下命令可以讓JConsole載入外掛並啟動:
jconsole -pluginpath C:Javajdk1.6.0_22demomanagementJTopJTop.jar
JConsole啟動後,連線到任意Java應用程式,便可以進入JTop頁面。
參考
《Java程式效能優化》葛一鳴著