jhat(Java Heap Analysis Tool),是一個用來分析java的堆情況的指令。是java虛拟機自帶的一種虛拟機堆轉儲快照分析工具。
可以用jhat指令将dump出來的hprof檔案轉成html的形式,然後通過http通路可以檢視堆情況。OK,現在來看看要怎麼做吧!
首先要一段會抛出OOM異常的代碼。
public class HeapOOM {
static class OOMObject{
}
public static void main(String[] args){
List<OOMObject> list = new ArrayList<>();
while(true){
list.add(new OOMObject());
}
}
編譯之後執行時加上參數:
-Xms20M -Xmx20M -Xmn10M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=“hprof檔案儲存路徑”
[email protected]:~$ java -Xms20M -Xmx20M -Xmn10M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/openjdk/HeapDump/ -cp /home/openjdk/NetBeansProjects/JavaApplication1/build/classes test_HeapOOM.HeapOOM
java.lang.OutOfMemoryError: Java heap space
Dumping heap to /home/openjdk/HeapDump/java_pid5239.hprof …
Heap dump file created [27583435 bytes in 4.678 secs]
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2245)
at java.util.Arrays.copyOf(Arrays.java:2219)
at java.util.ArrayList.grow(ArrayList.java:242)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:216)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)
at java.util.ArrayList.add(ArrayList.java:440)
at test_HeapOOM.HeapOOM.main(HeapOOM.java:24)
黑體字部分是我運作時的指令:
-Xms20M:設定JVM初始記憶體的大小
-Xmx20M:設定JVM最大記憶體
-Xmn10M:設定JVM年輕代大小
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=“hprof檔案儲存路徑”:這是讓堆OOM時dump出hprof檔案和檔案路徑
這裡把記憶體設定得很小是為了讓記憶體盡快溢出,然後抛出異常。
可以看到檔案輸出為 /home/openjdk/HeapDump/java_pid5239.hprof
現在我們有了需要展示的東西,就可以請出我們的jhat了,如下:
[email protected]:~$ jhat /home/openjdk/HeapDump/java_pid5239.hprof
Reading from /home/openjdk/HeapDump/java_pid5239.hprof…
Dump file created Fri Jan 25 20:53:37 CST 2019
Snapshot read, resolving…
Resolving 814957 objects…
Chasing references, expect 162 dots…
Eliminating duplicate references…
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
這樣就啟動起來了一個簡易的HTTP服務,端口号是7000,嘗試一下用浏覽器通路一下它,本地的可以通過http://localhost:7000,就可以得到這樣的頁面:
Other Queries 查詢資訊的方式
All classes including platform 把所有類資訊顯示出來(預設是不包括Java平台的類)
另外的檢視堆異常主要關注兩個:
Show instance counts for all classes (excluding platform) 平台外的所有對象資訊
Show heap histogram 先是堆的統計資訊
通過圖我們可以看到建立了810326個 test_HeapOOM.HeapOOM$OOMObject 的執行個體,再回顧一下我們的代碼,不正是在main函數裡邊不停的建立OOMObject對象導緻的記憶體溢出嗎?通過jhat我們可以很快定位到記憶體溢出問題的所在。
除了使用-XX:+HeapDumpOnOutOfMemoryError,還可以
1. 使用 jconsole 選項通過 HotSpotDiagnosticMXBean 從運作時獲得堆轉儲(生成hprof檔案)
2. 使用jmap
3. 使用 hprof 指令
以上三種方式來自Java指令學習系列(5):Jhat,還沒有具體實踐。