jhat(Java Heap Analysis Tool),是一個用來分析java的堆情況的命令。之前的文章講到過,使用jmap可以生成Java堆的Dump文件。生成dump文件之後就可以用jhat命令,將dump文件轉成html的形式,然後通過http訪問可以查看堆情況。
jhat命令解析會Java堆dump並啓動一個web服務器,然後就可以在瀏覽器中查看堆的dump文件了。
實例
一、導出dump文件
關於dump文件的生成可以看jmap命令的詳細介紹.
1、運行java程序
-
/**
-
* Created by hollis on 16/1/21.
-
*/
-
public class JhatTest {
-
public static void main(String[] args) {
-
while(true) {
-
String string = new String("hollis");
-
System.out.println(string);
-
}
-
}
-
}
2、查看該進程的ID
-
HollisMacBook-Air:apaas hollis$ jps -l
-
68680 org.jetbrains.jps.cmdline.Launcher
-
62247 com.intellij.rt.execution.application.AppMain
-
69038 sun.tools.jps.Jps
使用jps命令查看發現有三個java進程在運行,一個是我的IDEA使用的進程68680,一個是JPS命令使用的進程69038,另外一個就是上面那段代碼運行的進程62247。
3、生成dump文件
-
HollisMacBook-Air:test hollis$ jmap -dump:format=b,file=heapDump 62247
-
Dumping heap to /Users/hollis/workspace/test/heapDump ...
-
Heap dump file created
以上命令可以將進程6900的堆dump文件導出到heapDump文件中。
查看當前目錄就能看到heapDump文件。
除了使用jmap命令,還可以通過以下方式:
1、使用 jconsole 選項通過 HotSpotDiagnosticMXBean 從運行時獲得堆轉儲(生成dump文件)、
2、虛擬機啓動時如果指定了 -XX:+HeapDumpOnOutOfMemoryError 選項, 則在拋出 OutOfMemoryError 時, 會自動執行堆轉儲。
3、使用 hprof 命令
二、解析Java堆轉儲文件,並啓動一個 web server
-
HollisMacBook-Air:apaas hollis$ jhat heapDump
-
Reading from heapDump...
-
Dump file created Thu Jan 21 18:59:51 CST 2016
-
Snapshot read, resolving...
-
Resolving 341297 objects...
-
Chasing references, expect 68 dots....................................................................
-
Eliminating duplicate references....................................................................
-
Snapshot resolved.
-
Started HTTP server on port 7000
-
Server is ready.
使用jhat命令,就啓動了一個http服務,端口是7000
然後在訪問http://localhost:7000/
頁面如下:
三、分析
在瀏覽器裏面看到dump文件之後就可以進行分析了。這個頁面會列出當前進程中的所有對像情況。
該頁面提供了幾個查詢功能可供使用:
-
All classes including platform//
-
Show all members of the rootset
-
Show instance counts for all classes (including platform)
-
Show instance counts for all classes (excluding platform)
-
Show heap histogram
-
Show finalizer summary
-
Execute Object Query Language (OQL) query
一般查看堆異常情況主要看這個兩個部分:
Show instance counts for all classes (excluding platform),平臺外的所有對象信息。如下圖:
具體排查時需要結合代碼,觀察是否大量應該被回收的對象在一直被引用或者是否有佔用內存特別大的對象無法被回收。
用法摘要
這一部分放在後面介紹的原因是一般不太使用。
-
HollisMacBook-Air:~ hollis$ jhat -help
-
Usage: jhat [-stack <bool>] [-refs <bool>] [-port <port>] [-baseline <file>] [-debug <int>] [-version] [-h|-help] <file>
-
-J<flag> Pass <flag> directly to the runtime system. For
-
example, -J-mx512m to use a maximum heap size of 512MB
-
-stack false: Turn off tracking object allocation call stack.
-
-refs false: Turn off tracking of references to objects
-
-port <port>: Set the port for the HTTP server. Defaults to 7000
-
-exclude <file>: Specify a file that lists data members that should
-
be excluded from the reachableFrom query.
-
-baseline <file>: Specify a baseline object dump. Objects in
-
both heap dumps with the same ID and same class will
-
be marked as not being "new".
-
-debug <int>: Set debug level.
-
0: No debug output
-
1: Debug hprof file parsing
-
2: Debug hprof file parsing, no server
-
-version Report version number
-
-h|-help Print this help and exit
-
<file> The file to read
-stack false|true
關閉對象分配調用棧跟蹤(tracking object allocation call stack)。 如果分配位置信息在堆轉儲中不可用. 則必須將此標誌設置爲 false. 默認值爲 true.
-refs false|true
關閉對象引用跟蹤(tracking of references to objects)。 默認值爲 true. 默認情況下, 返回的指針是指向其他特定對象的對象,如反向鏈接或輸入引用(referrers or incoming references), 會統計/計算堆中的所有對象。
-port port-number
設置 jhat HTTP server 的端口號. 默認值 7000.
-exclude exclude-file
指定對象查詢時需要排除的數據成員列表文件(a file that lists data members that should be excluded from the reachable objects query)。 例如, 如果文件列列出了 java.lang.String.value , 那麼當從某個特定對象 Object o 計算可達的對象列表時, 引用路徑涉及 java.lang.String.value 的都會被排除。
-baseline exclude-file
指定一個基準堆轉儲(baseline heap dump)。 在兩個 heap dumps 中有相同 object ID 的對象會被標記爲不是新的(marked as not being new). 其他對象被標記爲新的(new). 在比較兩個不同的堆轉儲時很有用.
-debug int
設置 debug 級別. 0 表示不輸出調試信息。 值越大則表示輸出更詳細的 debug 信息.
-version
啓動後只顯示版本信息就退出
-J< flag >
因爲 jhat 命令實際上會啓動一個JVM來執行, 通過 -J 可以在啓動JVM時傳入一些啓動參數. 例如, -J-Xmx512m 則指定運行 jhat 的Java虛擬機使用的最大堆內存爲 512 MB. 如果需要使用多個JVM啓動參數,則傳入多個 -Jxxxxxx.
OQL
jhat還提供了一種對象查詢語言(Object Query Language),OQL有點類似SQL,可以用來查詢。
OQL語句的執行頁面: http://localhost:7000/oql/
OQL幫助信息頁面爲: http://localhost:7000/oqlhelp/
OQL的預發可以在幫助頁面查看,這裏就不詳細講解了。