jvm性能分析工具之-- Eclipse Memory Analyzer tool(MAT)

性能分析工具之-- Eclipse Memory Analyzer tool(MAT)(一)

前言

性能分析工具之-- Eclipse Memory Analyzer tool(MAT)(一)介紹了內存泄漏的前因後果。在本文中,將介紹MAT如何根據heapdump分析泄漏根源。由於測試範例可能過於簡單,很容易找出問題,但我期待藉此舉一反三。

一開始不得不說說ClassLoader,本質上,它的工作就是把磁盤上的類文件讀入內存,然後調用Java.lang.ClassLoader.defineClass方法告訴系統把內存鏡像處理成合法的字節碼。Java提供了抽象類ClassLoader,所有用戶自定義類裝載器都實例化自ClassLoader的子類。systemclass loader在沒有指定裝載器的情況下默認裝載用戶類,在Sun Java 1.5中既sun.misc.Launcher$AppClassLoader。更詳細的內容請參看下面的資料。

準備heap dump
請看下面的Pilot類,沒啥特殊的。

/**
 * Pilot class
 * @author rosen jiang
 */
package org.rosenjiang.bo;

public class Pilot{
    
    String name;
    int age;
    
    public Pilot(String a, int b){
        name = a;
        age = b;
    }
}


然後再看OOMHeapTest類,它是如何撐破heapdump的。

/**
 * OOMHeapTest class
 * @author rosen jiang
 */
package org.rosenjiang.test;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.rosenjiang.bo.Pilot;

public class OOMHeapTest {
    public static void main(String[] args){
        oom();
    }
    
    private static void oom(){
        Map<String, Pilot> map = new HashMap<String, Pilot>();
        Object[] array = new Object[1000000];
        for(int i=0; i<1000000; i++){
            String d = new Date().toString();
            Pilot p = new Pilot(d, i);
            map.put(i+"rosen jiang", p);
            array[i]=p;
        }
    }
}


是的,上面構造了很多的Pilot類實例,向數組和map中放。由於是StrongRefGC自然不會回收這些對象,一直放在heap中直到溢出。當然在運行前,先要在Eclipse中配置VM參數-XX:+HeapDumpOnOutOfMemoryError。好了,一會兒功夫內存溢出,控制檯打出如下信息。

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid3600.hprof 
Heap dump file created [78233961 bytes in 1.995 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space



java_pid3600.hprof
既是heap dump,可以在OOMHeapTest類所在的工程根目錄下找到。

 

MAT安裝

話分兩頭說,有了heap dump還得安裝MAT

MAT支持兩種安裝方式,一種是獨立版本,用戶不必安裝 EclipseIDE 環境,MAT 作爲一個獨立的 EclipseRCP 應用運行;另一種是插件版本,也就是說MAT 可以作爲 EclipseIDE 的一個插件,和Eclipse開發平臺集成。

獨立版本,下載地址:http://www.eclipse.org/mat/downloads.php

下載的zip包,解壓即可使用。下載頁圖示如下:


eclipse IDE集成安裝過程,可參看以下文章:

http://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-ma/index.html

安裝完成後,爲了更有效率的使用 MAT,我們可以配置一些環境參數。因爲通常而言,分析一個堆轉儲文件需要消耗很多的堆空間,爲了保證分析的效率和性能,在有條件的情況下,我們會建議分配給 MAT 儘可能多的內存資源。你可以採用如下兩種方式來分配內存更多的內存資源給 MAT

一種是修改啓動參數 MemoryAnalyzer.exe-vmargs -Xmx4g

另一種是編輯文件 MemoryAnalyzer.ini,在裏面添加類似信息 -vmargs– Xmx4g

說明:

1. MemoryAnalyzer.ini中的參數一般默認爲-vmargs– Xmx1024m,這就夠用了。假如你機器的內存不大,改大該參數的值,會導致MemoryAnalyzer啓動時,報錯:Failed to create the Java Virtual Machine。

2.當你導出的dump文件的大小大於你配置的1024m(說明1中,提到的配置:-vmargs– Xmx1024m),MAT輸出分析報告的時候,會報錯:An internal error occurred during: "Parsing heap dump from XXX”。適當調大說明1中的參數即可。


至此,MAT 就已經成功地安裝配置好了,Eclipse的左上角有Open Heap Dump按鈕,按照剛纔說的路徑找到java_pid3600.hprof文件並打開

先檢查一下 MAT生成的一系列文件:(截圖來自另一個例子)

可以看到 MAT工具提供了一個很貼心的功能,將報告的內容壓縮打包到一個 zip文件,並把它存放到原始堆轉儲文件的存放目錄下,這樣如果您需要和同事一起分析這個內存問題的話,只需要把這個小小的 zip包發給他就可以了,不需要把整個堆文件發給他。並且整個報告是一個 HTML格式的文件,用瀏覽器就可以輕鬆打開。

使用MAT打開dump文件,等待一會後,會彈出嚮導界面,保持默認設置,直接點Finish即是分析內存泄露問題。在點擊Finish後,會出現overview界面,您可以點擊工具欄上的 Leak Suspects 菜單項來生成內存泄露分析報告,也可以直接點擊餅圖下方的 Reports->Leak Suspects鏈接來生成報告。如圖:


MAT工具分析了heap dump後在界面上非常直觀的展示了一個餅圖,該圖深色區域被懷疑有內存泄漏,可以發現整個heap64M內存,深色區域就佔了99.5%。接下來是一個簡短的描述,告訴我們main線程佔用了大量內存,並且明確指出system class loader加載的"java.lang.Thread"實例有內存聚集,並建議用關鍵字"java.lang.Thread"進行檢查。所以,MAT通過簡單的兩句話就說明了問題所在,就算使用者沒什麼處理內存問題的經驗。在下面還有一個"Details"鏈接,在點開之前不妨考慮一個問題:爲何對象實例會聚集在內存中,爲何存活(而未被GC)?是的——Strong Ref,那麼再走近一些吧。如圖:


點擊了"Details"鏈接之後,除了在上一頁看到的描述外,還有Shortest Paths To the Accumulation PointAccumulated Objects部分,這裏說明了從GC root到聚集點的最短路徑,以及完整的reference chain。觀察Accumulated Objects部分,java.util.HashMapjava.lang.Object[1000000]實例的retained heap(size)最大,在上一篇文章中我們知道retained heap代表從該類實例沿着reference chain往下所能收集到的其他類實例的shallow heap(size)總和,所以明顯類實例都聚集在HashMapObject數組中了。這裏我們發現一個有趣的現象,既Object數組的shallow heapretained heap竟然一樣,通過Shallow and retained sizes一文可知,數組的shallow heap和一般對象(非數組)不同,依賴於數組的長度和裏面的元素的類型,對數組求shallow heap,也就是求數組集合內所有對象的shallow heap之和。好,再來看org.rosenjiang.bo.Pilot對象實例的shallow heap爲何是16,因爲對象頭是8字節,成員變量int4字節、String引用是4字節,故總共16字節。

在Accumulated Objects視圖中,retained heap佔用最多的是hashMap和object數組,爲啥它們會佔用這麼大的heap呢?這個時候需要分析hashMap和object數組中存放了一些什麼對象?接着往下看,來到了Accumulated Objects by Class區域,顧名思義,這裏能找到被聚集的對象實例的類名。org.rosenjiang.bo.Pilot類上頭條了,被實例化了290,325次,再返回去看程序,我承認是故意這麼幹的。還有很多有用的報告可用來協助分析問題,只是本文中的例子太簡單,也用不上。



爲了更多的瞭解MAT的功能,再舉一些例子(不提供對應的代碼):

例子二:

通過MAT發現heap dump問題所在,就需要尋找導致內存泄漏的代碼點。這時往往需要打開對象依賴關係樹形視圖,點擊如圖按鈕即可。 


這時會看到如下視圖:


這個視圖的右邊大區域可以看到對象的依賴關係,選中某個對象以後可以在左邊小窗口查看對象的一些屬性。如果屬性的值是一些內存地址你還可以點擊工具欄的搜索按鈕來搜索具體的對象信息。在進行具體分析的時候MAT只是起了幫助你進行分析的工具的功能,OOM問題分析沒有固定方法和準則。只能發揮你敏銳的洞察力,結合源代碼,對內存中的對象進行分析從而找到代碼中的BUG. 


例子三:

如何查看某一個對象佔用的內存空間 
1.按以下方式打開新窗口即可 ,如圖:


2.輸入類名(輸入類的全名) ,如圖:



轉載:http://blog.csdn.net/rachel_luo/article/details/8992461


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章