4.虛擬機性能監控與故障處理工具

1 概述

本文從實踐的角度去了解虛擬機內存管理的世界。給一個系統定位問題的時候,知識、經驗是關鍵基礎,數據是依據,工具是運用知識處理數據的手段。這裏說的數據包括:運行日誌、異常堆棧、GC日誌、線程快照(threaddump/javacore文件)、堆轉儲快照(headdump/hprof文件)等。經常使用適當的虛擬機監控和分析工具可以加快我們分析數據、定位解決問題的速度,但在學習工具前,也應當意識到工具永遠都是知識技能的一層包裝。
本文主要從JDK的常用命令工具和可視化工具兩方面進行介紹,希望對自己後續知識回顧和看到本文章的朋友有所幫助

2 JDK的命令行工具

如果需要在監控程序中加農運行中的程序,JDK1.5需要在陳旭啓動時添加參數"-Dcom.sun.management.jmxremote"開啓JMX管理功能,否則部分工具無法使用,目前JDK1.6+版本虛擬機默認是開啓了此功能。

名稱 主要作用
jps JVM Process Status Tool,顯示制定系統內所有的HOtSpot虛擬機進程
jstat JVM Statistics Monitoring Tool,用於手機HotSpot虛擬機各方面的運行數據
jinfo Configuration Info for Java,顯示虛擬機配置信息
jmap Memory Map for Java,生成虛擬機的內存轉儲快照(heapdump文件)
jhat JVM Heap Dump Browser,用於分析Heapdump文件,他會建立一個HTTP/HTML 服務器,讓用戶可以在瀏覽器上查看分析結果
jstack Stack Trace for Java,顯示虛擬機的現成快照

表1 Sun JDK 監控和故障處理工具

2.1 jps:虛擬機進程狀態工具

命令格式:

jsp [options] [hostid]
#樣例
jps -l

jps可以通過RMI協議查詢開啓RMI服務的遠程虛擬機進程狀態,hostid爲RMI註冊表中註冊的主機名。jps的其他常用選項間下表

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

表2 jps工具主要選項

2.2 jstat:虛擬機統計信息監視工具

jstat命令格式爲:

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

對於命令各種中的VMID與LVMID需要特別說明下:如果是本地虛擬機進程,VMID與LVMID是一致的,如果是遠程虛擬機進程,那VMID的格式應當是:

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

參數interval和count代表查詢間隔和次數,如果省略這兩個參數,說明只查詢一次。假設需要每250毫秒查詢一次進程 2345垃圾收集情況,一共查詢20次,那命令應該是:

jstat -gc 2345 250 20

說明:選項option代表着用戶希望查詢的虛擬機信息,主要分爲3類:類裝載、垃圾收集、運行期編譯情況,具體選項及作用請參考下表:

選項 作用
-class 監視類裝載,卸載數量,總空間以及類裝載所耗費的時間
-gc 監視Java堆狀況,包括Eden區,兩個survivor區、老年代、永久代等的容量、已用空間、GC時間合計等信息
-gccapacity 監視內容與-gc基本相同,但輸出主要關注Java堆各個區域使用到的最大、最小空間
-gcutil 監視內容與-gc基本相同,但輸出主要關注已使用空間佔總空間的百分比
-gccause 與gcutil功能一樣,但是會額外輸出導致上一次GC產生的原因
-gcnew 監視新生代GC狀況
-gcnewcapacity 監視內容與-gcnew基本相同,輸出朱啊喲關注使用到的最大、最小空間
-gcold 監視老年代GC狀況
-gcoldcapacity 監視內容與-gcold基本相同,輸出主要關注使用到的最大、最小空間
-gcpermcapacity 輸出永久代使用到的最大、最小空間
-compiler 輸出JIT編譯器編譯過的方法、耗時等信息
-printcompilation 輸出已被JIT編譯的方法

表3 jstat工具主要選項
例如:執行命令

jstat -gcutil 8945 250 5
S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
0.00 100.00  82.32  51.33  93.31  88.92    273   24.467    36   24.334   48.800
0.00 100.00  82.32  51.33  93.31  88.92    273   24.467    36   24.334   48.800
0.00 100.00  82.32  51.33  93.31  88.92    273   24.467    36   24.334   48.800
0.00 100.00  82.32  51.33  93.31  88.92    273   24.467    36   24.334   48.800
0.00 100.00  82.32  51.33  93.31  88.92    273   24.467    36   24.334   48.800

參數說明

Options — 選項,上面列出的選項
vmid    — VM的進程號,即當前運行的java進程號
interval– 間隔時間,單位爲毫秒
count  — 打印次數,如果缺省則打印無數次 
S0  — Heap上的 Survivor space 0 區已使用空間的百分比 
S1 — Heap上的 Survivor space 1 區已使用空間的百分比 
E  — Heap上的 Eden space 區已使用空間的百分比  (新生代)
O  — Heap上的 Old space 區已使用空間的百分比
P  — Perm space 區已使用空間的百分比  permanent
YGC — 從應用程序啓動到採樣時發生 Young GC 的次數
YGCT – 從應用程序啓動到採樣時 Young GC 所用的時間(單位秒)
FGC — 從應用程序啓動到採樣時發生 Full GC 的次數
FGCT – 從應用程序啓動到採樣時 Full GC 所用的時間(單位秒)
GCT — 從應用程序啓動到採樣時用於垃圾回收的總時間(單位秒)

需要遠程主機提供RMI支持,Sun提供的jstatd工具可以很方便地建立遠程RMI服務器

2.3 jinfo:Java配置信息工具

jinfo(Configuration Info for Java)的作用是實時地查看和調整虛擬機各項參數,使用JPS命令的-v參數可以查看虛擬機啓動時顯式制定的參數列表.
jinfo 命令格式:

jinfo [option] pid
選項 作用
-v 可以查看虛擬機啓動時顯示指定的參數列表
-flag 查詢虛擬機啓動時未被顯式指定的參數的系統默認值;jdk1.6+也可以使用java -XX:+PrintFlagsFinal 查看參數默認值
-sysprops 把虛擬機進程的System.getProperties()的內容打印出來;jdk1.5+已經支持

表4 jinfo工具主要選項
在這裏插入圖片描述

2.4 jmap:Java內存映像工具

jmap(Memory Map for Java)命令用於生成堆轉儲快照(一般稱爲headdump或dump文件)。如果不使用jmap命令,要想獲取Java堆轉儲快照,還有一些比較“暴力”的手段:比如可以用 -XX:+HeapOnOutOfMemoryError參數,可以讓虛擬機在OOM異常出現之後自動生成dump文件,通過-XX:+HeapDumpOnCtrlBreak參數則可以使用[ Ctrl ] + [ Break ]鍵讓虛擬機生成dump文件,又或者在Linux系統下通過Kill -3命令發送進程退出信號“嚇唬”一下虛擬機,也能拿到dump文件。

jmap的作用並不僅僅是爲了獲取dump文件,它可以查詢finalize執行隊列、Java堆和永久代的信息信息,如空間使用率、當前用的是哪種收集器等。

和jinfo命令一樣,jmap有不少功能在Windows平臺下都是受限的,除了生成dump文件的-dump選項和用於查看每個類的實例、空間佔用統計的-histo選項在所有操作系統都提供之外,其餘選項都只能在Linux/Solaris下使用。

jmap命令格式:

jmap [option] vmid
選項 作用
-dump 生成Java堆轉儲快照。格式爲:-dump:[live,]format=b,file=,其中live子參數說明是否只dup出存活的對象
-finalizerinfo 顯示在F-Queue中等待Finalizer線程執行finalize方法的對象,只在Linux/Solaris平臺下有效
-heap 顯示Java堆詳細信息,如使用哪種回收器、參數配置、分代狀況等。只在Linux/Solaris平臺下有效
-histo 顯示堆中對象統計信息,包括類、實例數量、合計容量
-permstat 以ClassLoader爲統計口徑顯示永久代內存狀態,只在Linux/Solaris平臺下有效
-F 當虛擬機進程對-dump選項沒有響應時,可使用這個選項強制生成dump快照,只在linux/Solaris平臺下有效

表5 jmap工具主要選項
例如:生成本地idea的快照

jmap -dump:format=b,file=idea.bin 8945
Dumping heap to /Users/hekui/idea.bin ...
Heap dump file created

2.5 jhat:虛擬機堆轉儲快照分析工具

jhat主要是集合jmap搭配使用,來分析jamp生成的堆轉儲快照,jhat內置了一個HTTP/HTML服務器,生成dump文件的分析結果後,可以直接在瀏覽器中查看。不過此工具比較簡陋不是很推薦使用,推薦使用Eclipse的Memory Analyzer或IBM的 HeapAnalyzer等工具。如下示例來顯示剛剛生成的idea快照

> jhat /Users/hekui/idea.bin
Reading from /Users/hekui/idea.bin...
Dump file created Sun May 05 22:40:35 CST 2019
Snapshot read, resolving...
Resolving 4315702 objects...
Chasing references, expect 863 dots......
Eliminating duplicate references..................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

然後直接在瀏覽器輸入http://localhost:7000即可看到對應的分析結果

2.6 jstack: Java堆棧跟蹤工具

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

jstack命令格式:

jstack [option] vmid
選項 作用(jstack工具主要選項)
-F 當正常輸出的請求不被響應時,強制輸出線程堆棧
-l 除堆棧外,顯示關於所的附加信息
-m 通過調用到本地方法的話,可以顯示C/C++的堆棧

表6 jstack工具主要選項
在這裏插入圖片描述
在JDK1.5中,java.lang.Thread類新增了一個getAllStackTraces()方法用於獲取虛擬機中所有線程的StackTraceElement對象。使用這個方法可以通過簡單的幾行代碼就完成了jstack的大部分功能,在實際項目中不妨調用這個方法做個管理員界面,可以隨時使用瀏覽器來查看線程堆棧,如下面代碼清單所示:

<%@ page import = "java.util.Map" %>
<html>
<head>
<title>服務器線程信息</title>
</head>
<body>
	<pre>
		<%
			for(Map.Entry<Thread, StackTraceElement[]> stackTrace : Thread.getAllStackTraces().entrySet()){
				Thread thread = (Thread)stackTrace.getKey();
				StackTraceElement[] stack = (StackTraceElement[]) stackTrace.getValue();
				if(thread.equals(Thread.currentThread())){
					continue;
				}
				out.print("\n線程:" + thread.getName() + "\n");
				for(StackTraceElement element : stack){
					out.print("\t" + element + "\n");
				}
			}
		%>
	</pre>
</body>
</html>

3 JDK常用可視化工具

JDK中除了提供大量的命令行工具外,還有兩個功能強大的可視化工具:JConsole和VisualVM,這兩個工具是JDK的正式成員,沒有被貼上“unsupported and experimental”的標籤。

2.1 JConsole:Java監視與管理控制檯

JConsole(Java Monitoring and Management Console)是一種基於JMX的可視化監視、管理工具。它管理部分的功能是針對JMX MBean進行管理,由於MBean可以使用代碼、中間服務器的管理控制檯或者所有符合JMX規範的軟件進行訪問。
啓動JConsole
以我本機安裝爲例,JDK安裝路徑爲C:\Program Files\Java\jdk1.8.0_131\bin>jconsole.exe;定位cd到JDK/bin目錄,執行"jconsole.exe",啓動JConsole後,將自動搜索出本機運行的所有虛擬機進程,不需要用戶再使用jps來查詢了。如下圖所示:雙擊選擇其中一個進程即可進行監控,也可以使用下面的“遠程進程”功能來連接遠程服務器,對遠程虛擬機進行監控。在這裏插入圖片描述
直接在這裏選擇這個需要監控的應用進程雙擊它進入JConsole主頁面(類似於JPS命令)
在這裏插入圖片描述
上圖爲JConsole的主界面,通過如上界面可以看出有內存、線程、類、VM概要、MBean等的監控
內存監控爲例,其他tab頁可自行研究了
“內存”頁籤相當於可視化的jstat命令,用於監視受收集管理的虛擬機內存(Java堆和永久代)的變化趨勢。以本監控示例的一個Springbootdemo工程示例,可以直觀的看到內存的變化
在這裏插入圖片描述
當然在內存中也分很多種,可以通過以下代碼自己運行查看運行狀態
在這裏插入圖片描述
以上監控如果感興趣可自己編寫一些實例進行運行監控空驗證,這樣對於掌握工具和熟悉工具更有幫助

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