天天看點

JVM學習筆記——jhat的使用

   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,就可以得到這樣的頁面:

JVM學習筆記——jhat的使用

Other Queries 查詢資訊的方式

All classes including platform 把所有類資訊顯示出來(預設是不包括Java平台的類)

另外的檢視堆異常主要關注兩個:

Show instance counts for all classes (excluding platform) 平台外的所有對象資訊

Show heap histogram 先是堆的統計資訊

JVM學習筆記——jhat的使用
JVM學習筆記——jhat的使用

  通過圖我們可以看到建立了810326個 test_HeapOOM.HeapOOM$OOMObject 的執行個體,再回顧一下我們的代碼,不正是在main函數裡邊不停的建立OOMObject對象導緻的記憶體溢出嗎?通過jhat我們可以很快定位到記憶體溢出問題的所在。

除了使用-XX:+HeapDumpOnOutOfMemoryError,還可以

1. 使用 jconsole 選項通過 HotSpotDiagnosticMXBean 從運作時獲得堆轉儲(生成hprof檔案)

2. 使用jmap

3. 使用 hprof 指令

以上三種方式來自Java指令學習系列(5):Jhat,還沒有具體實踐。