一、准備工作
1)工具下載: http://www.eclipse.org/mat/downloads.php
- 可以選擇eclipse插件的方式安裝
- http://download.eclipse.org/mat/1.3/update-site/
2)分析較大的dump文件(2G以上的dump文件,可能mat會出現oom)需要調整虛擬機參數
- 64位的系統在MemoryAnalyzer.ini設置-Xmx2g
- 32位的xp可以使用下面的方法進行嘗試:安裝jrockit 6.0的JDK,mat使用jrockit的jdk來啟動
-vm D:/Program Files/Java/jrockit-R28.0.0-jre1.6.0_17/bin/jrockit/jvm.dll -vmargs -Xmx1700m
3)准備DUMP見另一篇文章《JvisualVM-windows使用》
4)官方的一個例子:Memory Analysis in a Nutshell
二、開始使用MAT進行OOM分析
第一步,啟動mat ,選擇File->Open Heap Dump 選擇你的dump文件。下面開始等待,mat解析dump文件需要花一些時間,在解析的同時會在硬盤上寫入一些解析結果文件,這樣下次打開時速度會快很多。有時候mat在解析過程中可能會出現出錯的情況,這個時候可以將那些臨時文件刪除以后重試第一步,如果你的rp夠好的話重試也許會解析成功。
第二步,查看內存泄漏分析報表。mat解析完成以后會出現如下圖的提示:
因為我們就是為了查找內存泄漏的問題,所以保持默認選項直接點“Finish”就可以。
Mat會非常直觀的展現內存泄漏的可疑點,類似下面的報表可以直接看到某個線程占用了大量的內存
問題的詳細分析信息:
第三步,開始尋找導致內存泄漏的代碼點。這時往往需要打開對象依賴關系樹形視圖,點擊如圖按鈕即可。
這個視圖的左邊大區域可以看到對象的依賴關系,選中某個對象以后可以在左邊小窗口查看對象的一些屬性。如果屬性的值是一些內存地址你還可以點擊工具欄的搜索按鈕來搜索具體的對象信息。在進行具體分析的時候MAT只是起了幫助你進行分析的工具的功能,OOM問題分析沒有固定方法和准則。只能發揮你敏銳的洞察力,結合源代碼,對內存中的對象進行分析從而找到代碼中的BUG.
第四步,定位溢出的原因
- 通過Path to GC Roots或者Merge Shortest Paths to GC Roots
使用貼士:
關於shallow size、retained size
Shallow size就是對象本身占用內存的大小,不包含對其他對象的引用,也就是對象頭加成員變量(不是成員變量的值)的總和。在32位系統上,對象頭占用8字節,int占用4字節,不管成員變量(對象或數組)是否引用了其他對象(實例)或者賦值為null它始終占用4字節。故此,對於String對象實例來說,它有三個int成員(3*4=12字節)、一個char[]成員(1*4=4字節)以及一個對象頭(8字節),總共3*4 +1*4+8=24字節。根據這一原則,對String a=”rosen jiang”來說,實例a的shallow size也是24字節
Retained size是該對象自己的shallow size,加上從該對象能直接或間接訪問到對象的shallow size之和。換句話說,retained size是該對象被GC之后所能回收到內存的總和。為了更好的理解retained size,不妨看個例子。
把內存中的對象看成下圖中的節點,並且對象和對象之間互相引用。這里有一個特殊的節點GC Roots,正解!這就是reference chain的起點。
從obj1入手,上圖中藍色節點代表僅僅只有通過obj1才能直接或間接訪問的對象。因為可以通過GC Roots訪問,所以左圖的obj3不是藍色節點;而在右圖卻是藍色,因為它已經被包含在retained集合內。
所以對於左圖,obj1的retained size是obj1、obj2、obj4的shallow size總和;右圖的retained size是obj1、obj2、obj3、obj4的shallow size總和。obj2的retained size可以通過相同的方式計算。
如何查看某一個對象占用的內存空間
1.按以下方式打開新窗口即可
2.輸入類名(輸入類的全名)