MAT 全稱 Eclipse Memory Analysis Tools 是一個分析 Java堆數據的專業工具,能夠計算出內存中對象的實例數量、佔用空間大小、引用關係等,看看是誰阻止了垃圾收集器的回收工做,從而定位內存泄漏的緣由。php
a)OutOfMemoryError的時候,觸發full gc,但空間卻回收不了,引起內存泄露html
b)java服務器系統異常,好比load飆高,io異常,或者線程死鎖等,均可能經過分析堆中的內存對象來定位緣由java
https://www.eclipse.org/mat/downloads.php --下載地址服務器
http://help.eclipse.org/oxygen/index.jsp?topic=/org.eclipse.mat.ui.help/welcome.html --官網使用教程app
#參數配置:dom
分析堆轉儲文件須要消耗不少的堆空間,爲了保證分析的效率和性能,在有條件的狀況下,建議分配給 MAT 儘量多的內存資源。兩種方式分配內存資源給 MAT:eclipse
1)修改啓動參數 MemoryAnalyzer.exe -vmargs -Xmx4gjvm
2)編輯文件 MemoryAnalyzer.ini 添加 -vmargs – Xmx4gjsp
#4.1dump文件生成:工具
a)jvm內存溢出OutOfMemoryError自動生成dump內存快照
-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/home/work/oom_error.hprof
b)手動觸發生成
jps -v --查看jvm pid: 26041
生成jvm dump快照:
jmap -dump:format=b,file=/home/work/jinze/dump_26041_05231438.hprof 26041 --> 生成二進制堆棧文件。
jmap -heap 26041 --查看jvm堆棧內存佔用狀況
jmap -histo:live 26041 | head -20 --查看jvm內存佔用前20存活對象
基本概念:
Shallow Heap: 類對象自己佔用內存大小,不包含其引用的對象內存-> List對象佔用內存大小 4k
Retained Heap: 對象本身佔用內存 + 關聯引用對象佔用大小 -> List對象佔用內存大小 4k + User對象佔用內存大小 123k注:如一個ArrayList持有100,000個對象,每個佔用16 bytes,移除這些ArrayList能夠釋放16 x 100,000 + X,X表明ArrayList的shallow大小。相對於shallow heap,RetainedHeap能夠更精確的反映一個對象實際佔用的大小(由於若是該對象釋放,retained heap均可以被釋放)。
demo: private List<User> users;
Retained Set指的是這個對象自己和他持有引用的對象以及這些引用對象的Retained Set所佔內存大小的總和,官方的圖解以下所示。
從圖中能夠看出E的Retained Set爲E和G。C的Retained Set爲C、D、E、F、G、H。
MAT所定義的支配樹就是從上圖的引用樹演化而來。在引用樹當中,一條到Y的路徑必然會通過X,這就是X支配Y。X直接支配Y則指的是在全部支配Y的對象中,X是Y最近的一個對象。
內存溢出排除方法思路:
1.看GC日誌 126719K->126719K(126720K) [回收先後內存大小不變或一直增加無減小波動,則可能有內存溢出問題]
2.生成堆內存 heap dump(某個時間點jvm中全部活躍的對象的堆內存快照)
3.MAT查看: 過濾列舉對象(傳入或傳出的對象引用)、分組排序顯示
1. Histogram or dominator_tree: Retained Heap倒敘排序 查看內存佔用
2. 定位問題代碼段: 看有沒有GC Root指向:若無GC Root指向 -> Merge Shortest Paths to GC Roots -> exclude all phantom/weak/soft etc.reference(排除虛弱軟引用) ->查找GC Root線程
File > Open Heap Dump > Leak Suspects Report -打開dump文件
Overview > Actions > The Histogram (查看堆棧中java類 對象[Objects]個數、[Shallow Heap]individual objects此類對象佔用大小、[Retained Heap]關聯對象佔用大小) -> Retained Heap倒敘排序(重點關注內存佔用高對象) -> Merge Shortest Paths to GC roots -> exclude all phantom/weak/soft etc.reference(排除全部虛弱軟引用) ->查看剩餘未被回收的強引用對象佔用緣由 & GC Roots。
Overview > Actions > dominator_tree (查看堆中內存佔用最高的對象的線程調用堆棧) dominator_tree -> 對象調用堆棧樹-查找內存佔用最高對象(Retained Heap倒敘排序) -> Paths to GC Roots -> exclude all phantom/weak/soft etc.reference (排除全部虛弱軟引用) -查找GC Root線程 -> 查找未釋放的內存佔用最高的代碼邏輯段(極可能是產生內存溢出代碼)
MAT打開dump文件,生成分析報告: File > Open Heap Dump > Leak Suspects Report
Open Heap Dump
Leak Suspects Report - Finish -分析內存泄漏可疑點
1.Overview
Overview概要信息,好比空間大小、類的數量、對象實例數量、類加載器等等
Atcion裏面提供了多種分析維度: (重點關注 Histogram & Dominator Tree 便可)
Histogram 按類列出內存中的對象,對象的個數以及大小。
Dominator Tree 支配樹,分析對象的引用關係。
Leak Suspects經過MA自動分析泄漏的緣由。
Overview
##2.Histogram
Overview > Actions > The Histogram (查看堆棧中java類對象[Objects]個數、[Shallow Heap]individual objects此類對象佔用大小、[Retained Heap]關聯對象佔用大小)
按類列出全部實例對象個數Objects、Shallow Heap(對象自己佔用內存大小)、Retained Heap (對象自己佔用內存大小+關聯引用對象佔用內存) 內存佔用狀況,能夠經過Class Name過濾篩選 ;or 按照對象 或 class 引用 和 被引用 展現: List objects or Show objects by class: [with incoming references 列出哪些類引入該類;with outgoing references 出該類引用了哪些類]
Actions > The Histogram (查看堆棧中java類 對象[Objects]個數、[Shallow Heap]individual objects此類對象佔用大小、[Retained Heap]關聯對象佔用大小) -> Retained Heap倒敘排序(重點關注內存佔用高對象) -> Merge Shortest Paths to GC roots -> exclude all phantom/weak/soft etc.reference(排除全部虛弱軟引用) ->查看剩餘未被回收的強引用對象佔用緣由 & GC Roots。
## 3.Dominator Tree
支配樹,分析對象的引用關係。 對象內存佔用&佔比
dominate_tree -> 對象調用堆棧樹-查找內存佔用最高對象(Retained Heap倒敘排序) -> Paths to GC Roots -> exclude all phantom/weak/soft etc.reference(排除全部虛弱軟引用) -查找GC Root線程-> 定位未釋放內存代碼段
Actions > dominator_tree (查看堆中內存佔用最高的對象的線程調用堆棧) -> 對象調用堆棧樹-查找內存佔用最高對象(Retained Heap倒敘排序) -> Paths to GC Roots -> exclude all phantom/weak/soft etc.reference (排除全部虛弱軟引用) -查找GC Root線程 -> 查找未釋放的內存佔用最高的代碼邏輯段(極可能是產生內存溢出代碼)
##4.Leak Suspects --自動分析內存溢出可疑點
MAT插件會給出一份可疑的分析報告,很是方便,咱們只需結合源代碼稍加分析到底哪一個Problem纔是引起問題真正緣由所在。點點看 Details,如有問題你很容易發現你熟悉的代碼段。
##5.OQL:
OQL全稱爲Object Query Language,相似於SQL語句的查詢語言,可以用來查詢當前內存中知足指定條件的全部的對象。
API: http://help.eclipse.org/luna/index.jsp?topic=/org.eclipse.mat.ui.help/reference/oqlsyntax.html
##6. 對比dump 堆棧文件
由於咱們這個例子很簡單,能夠經過上面的方法來找到內存泄漏的緣由,可是複雜的狀況就須要經過對比hpof文件來進行分析了。使用步驟爲:
操做應用,生成第一個hpof文件。
進行一段時間操做,再生成第二個hpof文件。
用MAT打開這兩個hpof文件。
將第一個和第二個hpof文件的Dominator Tree或者Histogram添加到Compare Basket中,以後選中2個文件對比便可
2個dump文件對比尋找波動差別(關注差別波動大的對象)
參考:
https://blog.csdn.net/itomge/article/details/48719527
https://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-ma/index.html
http://liuwangshu.cn/application/performance/ram-5-mat.html