Mat 用法

MAT

MAT工具全稱爲Memory Analyzer Tool,一款詳細分析Java堆內存的工具,該工具非常強大,爲了使用該工具,我們需要hprof文件.

HPROF文件存儲的是特定時間點,java進程的內存快照。有不同的格式來存儲這些數據,總的來說包含了快照被觸發時java對象和類在heap中的情況。由於快照只是一瞬間的事情,所以heap dump中無法包含一個對象在何時、何地(哪個方法中)被分配這樣的信息。

幾個關鍵概念

  • Histogram:列出內存中的對象,對象的個數以及大小
  • Dominator Tree:列出最大的對象以及其依賴存活的Object (大小是以Retained Heap爲標準排序的)
  • Top Consumers : 通過圖形列出最大的object
  • Duplicate Class:通過MAT自動分析泄漏的原因
  • Shallow heap : 對象本身佔用內存的大小,不包含其引用的對象。
    (常規對象(非數組)的Shallow size有其成員變量的數量和類型決定。數組的shallow size有數組元素的類型(對象類型、基本類型)和數組長度決定. 因爲不像c++的對象本身可以存放大量內存,java的對象成員都是些引用。真正的內存都在堆上,看起來是一堆原生的byte[], char[], int[],所以我們如果只看對象本身的內存,那麼數量都很小。所以我們看到Histogram圖是以Shallow size進行排序的,排在第一位第二位的是byte,char 。)
  • Retained Heap : 它表示如果一個對象被釋放掉,那會因爲該對象的釋放而減少引用進而被釋放的所有的對象(包括被遞歸釋放的)所佔用的heap大小。
    (於是,如果一個對象的某個成員new了一大塊int數組,那這個int數組也可以計算到這個對象中。相對於shallow heap,Retained heap可以更精確的反映一個對象實際佔用的大小(因爲如果該對象釋放,retained heap都可以被釋放)。)
  • outgoing references :表示該對象的出節點(被該對象引用的對象)。
  • incoming references :表示該對象的入節點(引用到該對象的對象)。
  • GC Root: GC發現通過任何reference chain(引用鏈)無法訪問某個對象的時候,該對象即被回收。所以JVM就是GC Roots。
  • Unreachable指的是可以被垃圾回收器回收的對象,但是由於沒有GC發生,所以沒有釋放,這時抓的內存使用中的Unreachable就是這些對象。

1. 預覽信息

打開dump 文件,通常我們需要關注一下幾個重要信息, 內存佔用餅圖,Actions部分的Histogram, Top Consumers.
我們打開Top Consumers,會生成一個報告,我們可以Biggets Objects overview, 能夠看到主要內存佔用者

Paste_Image.png

 

點擊下面的biggest Objects 可以查看具體的地址。
還有Biggest Top Level Dominator Classes , 可以看到主要佔用內存的都是些什麼東東。

2. dump分析

2.1 Histogram

MAT中Histogram的主要作用是查看一個instance的數量,一般用來查看自己創建的類的實例的個數。 可以分不同維度來查看對象的Dominator Tree視圖,Group by class、Group by class loader、Group by package 和Histogram類似,時間久了,通過多次對比也可以把溢出對象找出來。 Histogram 中可以分Group,Thread 區分信息。 通常爲:選中某一項-> show objects and class -> by incoming reference->merge shortest path to gc root -> exclude weadk reference
等流程來查看具體情況。

可以在上面過濾相關包名,查看到具體類型, 關注objects個數, 表示內存dump 中有多少個相關類型對象, 比如不改存在的 對象存在了,或者有的對象內存中有太多的份數, 這樣就可以進行一個全面分析。

也可以選擇Group by package ,這樣方便根據package來進行分析。

 

Paste_Image.png

也可以選擇thread來進行分析, 這樣查看佔用內存最多的線程,這些線程可能爲有內存問題的線程。

點擊右鍵常用的幾個選項:

  • List Objects -> with incoming references 查看這個對象被哪些外部對象引用
  • List Objects-> with outcoming references 查看這個對象持有的外部對象引用
  • Path to GC Roots -> exclude ... references 查看這個對象的GC Root,不包含xxx引用,剩下的基本就是強引用了。因爲只有強引用一直存在,gc就一直無法回收該對象,從而也就出現內存泄露。
  • Merge shortest path to GC root 找到從GC根結點到一個對象或者一組對象的共同路徑。從這裏可以查看到對象的引用關係。

2.2 Debug Bitmap

圖片一直是內存佔用的一個大頭,也是引起內存泄露,OOM的常客。所以對圖片的分析是需要非常瞭解,這樣才能更好的優化項目。*注意:圖片在內存中佔用的大小:ARGB_8888 類型的圖片 爲 內存中圖片寬度*內存中圖片高度4, 此處需要注意原始圖片寬高和內存圖片寬高不一致,包括拉伸和壓縮,尤其是圖片位置放錯,比如1080p設備,xxxhdpi下面沒有圖片,會去別的目錄下尋找圖片,此時將會對圖片拉伸。 **
下面我們來看一下圖片的處理。通常dump信息中圖片表現爲兩種類型,Bitmap, byte[]。我們需要知道該圖片是哪張圖片,這樣才能好優化相關的圖片代碼。

  • Bitmap類型
    在mat中通常能夠看到bitmap類型,佔用了大量的內存,如下面這張圖片,在內存中佔用2M。 我們可以打開,查看mBuffer變量。

     

    Paste_Image.png

選中mBuffer-> 右鍵選中Copy-> 選擇Save Value To File -> 生成一個xxx.data 文件。

  • Byte[] 類型
    如下,查看byte的 in comming, 即可看到它是一個bitmap,此時如下圖,我們可以直接將該byte數據寫入xxx.data 文件。

     

    Paste_Image.png

下一步是選中對應的bitmap,打開Inspector 窗口,查看bitmap的尺寸,並且使用GIMP工具(可以安裝一個,開源的)打開剛纔的data文件,圖像類型選擇RGB Alpha, 寬度和高度填入圖像的寬高,打開即可。

Paste_Image.png

Paste_Image.png

2.3 堆對比

通常爲了分析內存是否泄露,內存是否持續增長但沒有釋放等問題,我們需要dump兩次來進行內存堆的對比。

打開兩個或多個dump文件,打開Navigation History視圖,點擊Historgam,選擇Add to Comp are Basket,最後選中Compare the Result 。

Paste_Image.png

在對比結果中,主要分析類型或者對象的數量是否有變化, 內存是否有變化。

通過以上手段,我們可以定位到大部分內存問題。

 

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