背景
筆記中躺了很久的文章,今天用到Mat時發現之前寫的內容還算清晰,分享出來;
如下所舉例使用的dump文件是針對之前使用的ignite庫溢出時的dump文件;關於ignite的概念此處不再敘述,本篇文章重點則在於Mat即可
Mat的作用
MAT是Memory Analyzer tool的縮寫,是一種快速,功能豐富的Java堆分析工具,能幫助你查找內存泄漏和減少內存消耗。很多情況下,我們需要處理測試提供的hprof文件,分析內存相關問題,那么MAT也絕對是不二之選。 Eclipse可以下載插件結合使用,也可以作為一個獨立分析工具使用;下載地址:https://pan.baidu.com/s/1NDUR0E3WGrktm1qwoZHWfg
提取碼:agxr ;不用謝,雷鋒
Mat的使用步驟
打開Mat后File>OpenHeapDump打開一個對應的dump文件后,此時對應的打開后結果如圖所示:
默認情況下打開該dump文件后,直接展示的就是一個Overview(概覽)的頁簽,其中可以看到上面標注為(1,2)的地方所對應的圖標與Overview頁簽中所對應的部分圖標是相似的;如果你不小心關掉了Overview的頁簽,那么直接單擊當前dump頁簽第一行導航欄的第一個 I字的圖標即可,同理,如果此時想要打開Histogram,那么在不打開Overview的情況下,直接點擊第一行導航欄的第二個圖標即可;......
Overview下功能解釋
Overview頁簽下分別包含了:Actions,Reports,Step By Step 三大塊功能;每一塊功能下的子集所對應的作用分別是:
-
Actions:
-
Histogram 列出每個類所對應的對象個數,以及所占用的內存大小;
-
Dominator Tree 以占用總內存的百分比的方式來列舉出所有的實例對象,注意這個地方是直接列舉出的對應的對象而不是類,這個視圖是用來發現大內存對象的
-
Top Consumers:按照類和包分組的方式展示出占用內存最大的一個對象
-
Duplicate Classes:檢測由多個類加載器所加載的類信息(用來查找重復的類)
-
-
Reports:
-
Leak Suspects:通過MAT自動分析當前內存泄露的主要原因
-
Top Components:Top組件,列出大於總堆1%的組件的報告
-
-
Step By Step:
- Component Report:組件報告,分析屬於公共根包或類加載器的對象;
上述所有被標注加粗的部分,是內存溢出dump分析時較為常用的功能點也是下面主要講解的內容。
原創聲明:作者:Arnold.zhao 博客園地址:https://www.cnblogs.com/zh94
Histogram
通過Histogram 列出每個類所對應的對象個數,以及所占用的內存大小;
此處選中一個ClassName單擊后,通過左上角Inspector可以看到當前類的回收情況,內存地址,等
補充解釋:
-
字段一:表示當前類所對應的對象數量
-
字段二:Shallow Size是對象本身占據的內存的大小,不包含其引用的對象。對於常規對象(非數組)的Shallow Size由其成員變量的數量和類型來定,而數組的ShallowSize由數組類型和數組長度來決定,它為數組元素大小的總和;
-
字段三:Retained Size=當前對象大小+當前對象可直接或間接引用到的對象的大小總和。(間接引用的含義:A->B->C,C就是間接引用) ,並且排除被GC Roots直接或者間接引用的對象;
關於紅框內的Statics,Attributes,Classhierarchy,Value則分別表示當前類的靜態變量,屬性,當前類的層次結構圖,以及當前類所對應的值Value;
注意:當前Histogram的列屬性:ClassName,Objects,ShallowHeap,RetainedHeap這幾個列屬性下面都是有提供一個輸入框,通過該輸入框可以進行相關類的檢索,比如:在ClassName下輸入一個正則.quark.那么則獲取到所有包路徑為quark的類信息;
Dominator Tree
以占用總內存的百分比的方式來列舉出所有的實例對象,可以用來發現大內存對象;
如上圖所示:可以看到ConcurrentHashMap@0x60191cfa8這個對象占據了98.92%的堆大小,所以基本就可以斷定,當前項目之所以會down機的主要原因是,ConcurrentHashMap溢出所導致的問題;
那么當我們需要查看,當前該ConcurrentHashMap@0x60191cfa8對象都引用了那些數據,以及當前該對象是被那幾個對象所引用的,如何查看?
鼠標在當前所要查看的對象右鍵,點擊List Objects可以看到分別提供了:with outgoing references(查看當前該對象的所有的引用信息) 和 with incoming references(查看當前該對象是被那幾個對象所引用的) ;
原創聲明:作者:Arnold.zhao 博客園地址:https://www.cnblogs.com/zh94
Leak Suspects
通過MAT自動分析當前內存泄露的主要原因
可以看到,當前MAT所給出內存泄露的主要原因是:當前實例java.util.concurrent.ConcurrentHashMap被加載自system class loader,共占用了 98.92%的堆內存,這個實例被引用自org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl並且這個CacheObjectBinaryProcessorImpl這個對象是加載自LaunchedURLClassLoader這個類加載器;
並且還給出了所對應的主要關鍵詞是:
java.util.concurrent.ConcurrentHashMap$Node[]
java.util.concurrent.ConcurrentHashMap
org.springframework.boot.loader.LaunchedURLClassLoader @ 0x6000a6860
基本上可以說是很詳細了,一語中的,如果想要查看明細,可以直接點擊detail,里面有更詳細的說明,如下圖所示:
上圖分別說明了到該內存泄漏的對象的最快路徑,也就是列出了當前ConcurrentHashMapConcurrentHashMap@0x60191cfa8這個對象所對應的被引用關系:可以看到當前引起內存泄漏的ConcurrentHashMap被CacheObjectBinaryProcessorImpl@0x60191cea8這個對象的metadataLocCache這個屬性所引用,而CacheObjectBinaryProcessorImpl這個對象又被GridKernalContextImpl @ 0x601821bf8這個對象的cacheObjeProc這個屬性所引用,以此遞推;
除此之外,還有以下三個被隱藏的信息,點擊即可查看明細:
Accumulated Objects in Dominator Tree (主控樹中的累積對象),Accumulated Objects by Class in Dominator Tree(主控樹中的按類累積對象 ,All Accumulated Objects by Class (按類列出所有的累積對象)
原創聲明:作者:Arnold.zhao 博客園地址:https://www.cnblogs.com/zh94
Overview功能說明結尾
通過上述的解釋應該對當前Overview下的功能使用已經有了一個大概的了解,需要注意的是,Histogram 以及Dominator Tree時所主要提及的Shallow Size以及Retained Size以及在所列出的對象上右鍵查看引用關系,GCROOTS,以及左上角所展示的屬性明細等功能 是適用於所有的功能模塊的,后續不再贅述;
一級導航欄功能說明
查看完上述關於Overview中的功能說明后,此處再來看一下Overview中不包含的一些功能
Thread_Overview
如下圖所示,點擊一級導航欄的第5個圖標,可以用來查看當前進程dump時的所有線程的堆棧信息,通過分析下面所對應的堆棧信息,可以很快速的定位到對應的線程所執行的方法等層級關系,以此來定位對應的異常問題;
OQL
用於查詢Java堆的類SQL查詢語言
Heap Dump Overview
點擊一級導航欄的第6個圖標的下拉框下的 Heap Dump Overview,可以查看全局的內存占用信息
Find Object by address
查看指定內存地址所對應的對象信息;
常見溢出的幾個場景
1、線程所引用對象溢出
2、靜態屬性對象溢出
線程棧所引用對象溢出的場景,如下:
Mat各功能內還有很多小的子功能,使用過程中可逐步嘗試,此處不再贅述