直方圖:列舉實例類
Dominator Tree: List the biggest objects and what they keep alive.統治者樹:列出最大的對象和他們保持活着。
Top Consumers: Print the most expensive objects grouped by class and by package.頂部的消費者:打印最昂貴的對象按類和包。
重復的類:檢測由多個類加載器加載的類。
泄漏嫌疑人:包括泄漏嫌疑人和系統概述
Top Components: list reports for components bigger than 1 percent of the total heap.頂部件:列表報告成分大於百分之1的總的堆。
部分報告:分析對象,屬於一個共同的根包或類加載器。
Class Name
Shallow Heap
Retained Heap
Class Name
Shallow Heap
Retained Heap
Accumulated Objects by Class:
Label
Number of Objects
Used Heap Size
Retained Heap Size
通常我們都會采用下面的“三步曲”來分析內存泄露問題:
首先,對問題發生時刻的系統內存狀態獲取一個整體印象。
第二步,找到最有可能導致內存泄露的元凶,通常也就是消耗內存最多的對象
查看報告之一:內存消耗的整體狀況
圖 7. 內存泄露分析報告
如圖 7 所示,在報告上最醒目的就是一張簡潔明了的餅圖,從圖上我們可以 清晰地看到一個可疑對象消耗了系統 99% 的內存。
在 圖的下方還有對這個可疑對象的進一步描述。我們可以看到內存是由 java.util.Vector 的實例消耗的,com.ibm.oti.vm.BootstrapClassLoader 負責 這個對象的加載。這段描述非常短,但我相信您已經可以從中找到很多線索了, 比如是哪個類占用了絕大多數的內存,它屬於哪個組件等等。
接下來,我們應該進一步去分析問題,為什么一個 Vector 會占據了系統 99% 的內存,誰阻止了垃圾回收機制對它的回收。
查看報告之二:分析問題的所在
首 先我們簡單回顧下 JAVA 的內存回收機制,內存空間中垃圾回收的工作由垃 圾回收器 (Garbage Collector,GC) 完成的,它的核心思想是:對虛擬機可用內 存空間,即堆空間中的對象進行識別,如果對象正在被引用,那么稱其為存活對 象,反之,如果對象不再被引用,則為垃圾對象,可以回收其占據的空間,用於 再分配。
在垃圾回收機制中有一組元素被稱為根元素集合,它們是 一組被虛擬機直接引 用的對象,比如,正在運行的線程對象,系統調用棧里面的對象以及被 system class loader 所加載的那些對象。堆空間中的每個對象都是由一個根元素為起點 被層層調用的。因此,一個對象還被某一個存活的根元素所引用,就會被認為是 存活對象,不能被回收,進行內存釋放。因此,我們可以通過分析一個對象到根 元素的引用路徑來分析為什么該對象不能被順利回收。如果說一個對象已經不被 任何程序邏輯所需要但是還存在被根元素引用的情況,我們可以說這里存在內存 泄露。
現在,讓我們開始真正的尋找內存泄露之旅,點擊“Details ”鏈接,可以看 到如圖 8 所示對可疑對象 1 的詳細分析報告。
圖 8. 可疑對象 1 的詳細分析報告
我們查看下從 GC 根元素到內存消耗聚集點的最短路徑:
圖 9. 從根元素到內存消耗聚集點的最短路徑
我們可以很清楚的看到整個引用鏈,內存聚集點是一個擁有大量對象的集合, 如果你對代碼比較熟悉的話,相信這些信息應該能給你提供一些找到內存泄露的 思路了。
接下來,我們再繼續看看,這個對象集合里到底存放了什么,為什么會消耗掉 如此多的內存。
圖 10. 內存消耗聚集對象信息
在這張圖上,我們可以清楚的看到,這個對象集合中保存了大量 Person 對象 的引用,就是它導致的內存泄露。
至此,我們已經擁有了足夠的信息去尋找泄露點,回到代碼,我們發現,是下 面的代碼導致了內存泄露 :
清單 1. 內存泄漏的代碼段
while (1<2)
{
Person person = new Person("name","address",i);
v.add(person);
person = null;
}
總結
從上面的例子我們可以看到用 MAT 來進行堆轉儲文件分析,尋找內存泄露非 常簡單,尤其是對於新手而言,這是一個很好的輔助分析工具。但是,MAT 絕對 不僅僅是一個“傻瓜式”內存分析工具,它還提供很多高級功能,比如 MAT 支持 用 OQL(Object Query Language)對 heap dump 中的對象進行查詢,支持對線 程的分析等,有關這些功能的使用可以參考 MAT 的幫助文檔。
1、MAT是什么?
MAT(Memory Analyzer Tool),一個基於Eclipse的內存分析工具,是一個快速、功能豐富的JAVA heap分析工具,它可以幫助我們查找內存泄漏和減少內存消耗。使用內存分析工具從眾多的對象中進行分析,快速的計算出在內存中對象的占用大小,看看是誰 阻止了垃圾收集器的回收工作,並可以通過報表直觀的查看到可能造成這種結果的對象。
2.為什么使用MAT?
當服務器應用占用了過多內存的時候,會遇到OutOfMemoryError。如何快速定位問題呢?Eclipse MAT的出現使這個問題變得非常簡單。它能夠離線分析dump的文件數據。
Eclipse MAT是SAP公司貢獻的一個工具,可以在Eclipse網站下載到它,完全免費的。它可比Sun提供的內存鏡像分析工具jhat要強太多了。
3.
首頁:http://www.eclipse.org/mat/
插件更新地址:
http://download.eclipse.org/mat/1.0/update-site/
先調用jdk的工具得到heap使用情況
我安裝的是jdk1.6
C:/>java -version
java version "1.6.0_11"
Java(TM) SE Runtime Environment (build 1.6.0_11-b03)
Java HotSpot(TM) Client VM (build 11.0-b16, mixed mode, sharing)
調用jdk工具jps查看當前的java進程
C:/>jps
3504 Jps
3676 Bootstrap
3496 org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar
調用jmap工具得到信息
C:/>jmap -dump:format=b,file=heap.bin 3676
Dumping heap to C:/heap.bin ...
Heap dump file created
這時,我們的C盤根目錄,就生成了heap.bin文件,用eclipse的file---->open打開這個文件,首先是一個啟動圖:
這里可以選擇查看
1、內存泄露報表,自動檢查可能存在內存泄露的對象,通過報表展示存活的對象以及為什么他們沒有被垃圾收集;
2、對象報表,對可穎對象的分析,如字符串是否定義重了,空的collection、finalizer以及弱引用等。
我這里選擇的是查看內存報表,以下是截的簡略圖:
通過報表展示,蠻清楚的,下面還有詳細的說明,這里就沒有帖圖了,有興趣的可以繼續探究。