Java記憶體分析利器MAT使用詳解
這是一篇閱讀MAT helper的筆記。Heap dump是java程式在特定時間的一個記憶體快照。通常在觸發heap dump之前會進行一次full gc,這樣dump出來的內容就包含的是被gc後的物件。
dump檔案包含的內容:
1,全部的物件:類,域,原生值和引用;
2,全部的類:classloader,類名,超類,靜態域;
3,GC root:被JVM定義的可觸達的物件;
4,執行緒棧和本地變數:執行緒的call stack,本地物件每幀的資訊。
dump檔案不包含記憶體的分配資訊,因此無法查詢誰建立了哪個物件這樣的資訊。
Shallow heap是一個物件佔用的記憶體空間,一個物件需要32或者64bits。
Retained set of X是X在被jvm gc回收後被remove的一組object。
Retained heap of X是在retained set of X中的所有物件的shallow heap size的和。換句話說就是保持X活著需要的記憶體空間。
通俗的講,shallow heap是一個物件在記憶體中的實際空間,而retained heap是一個物件被gc回收後記憶體釋放出來的空間。
這張圖可以看懂什麼是leading set什麼是retained set。
Dominator tree:定義一個物件x dominate 物件y,當每一條從root開始到y的路徑都經過x。說白了就是隻要有y物件的存活,那麼一定會有一個x物件。Dominator tree就是將物件引用圖轉換成的樹形結構。幫助發現在物件間保持alive的依賴,同時也能識別出retained記憶體的最大的chunk。 Immediate dominator x of y是離y最近的dominator。
Dominator tree有幾個屬性:
1,物件x的子樹包含的物件(x dominate的物件集),代表了x的retained set;
2,如果x是y的immediate dominator,那麼x的immediate dominator同樣dominate y,以此類推;
3,dominate tree中的邊不代表物件引用圖裡對應的邊,並非嚴格的直接的物件引用。
這張圖反應了一個物件引用圖轉換成dominator tree的示例。
Gc root:一個gc根就是一個物件,這個物件從堆外可以訪問讀取。以下一些方法可以使一個物件成為gc根。
1,System class:被Bootstrap或者system類載入器載入的類,比如rt.jar裡的java.util.*;
2,JNI local:native程式碼裡的local變數,比如使用者定義的JNI程式碼和JVM的內部程式碼;
3,JNI global:native程式碼裡的global變數;
4,Thread block:當前活躍的執行緒block中引用的物件;
5,Thread:已經啟動並且沒有stop的執行緒;
6,busy monitor:被呼叫了wait()或者notify()或者被synchronized同步的物件,如果是synchronized方法,那麼靜態方法指的類,非靜態方法指的是物件;
7,java local:local變數,比如方法的入參和方法內建立的變數;
8,native stack:native程式碼裡的出入引數,比如file/net/IO方法以及反射的引數;
9,finalizable:在一個佇列裡等待它的finalizer 執行的物件;
10,unfinalized:一個有finalize方法的物件,還沒有被finalize,同時也沒有進入finalizer佇列等待finalize;
11,unreachable:不會被觸碰到的物件,在MAT裡被標記為root用來retain object,否則是不會在分析中出現的;
12,java stack frame:java棧幀包含了本地變數,當dump被解析時且在preferences裡設定過把棧幀當做物件,這時才會產生;
13,unknown:位置的root型別。
接下來是一些獲取dump的方法:
1,在oom時dump:JVM引數:-XX:+HeapDumpOnOutOfMemoryError
2,互動式環境下dump:
1)JVM引數:-XX:+HeapDumpOnCtrlBreak
2)用外部tools:jmap -dump:format=b,file=<filename.hprof> <pid>
3)用外部tools:jconsole
4)用外部工具:MAT
5)kill -3 <pid>
6)jstack -l <pid> > <dumpfile>
一些排查方法:
1,通過top consumers查詢大物件,可以按照class、classloader和package進行group by;
2,通過immediate dominator找到責任物件,對於快速定位一組物件的持有者非常有用,這個操作直接解決了“誰讓這些物件alive”的問題,而不是“誰有這些物件的引用”的問題,更直接高效;
3,執行classloader分析,這個重要性體現在亮點:第一,應用使用不同的classloader載入類,第二,不同 classloader載入的類儲存在不同的永久代,這理論上也是可以被回收的。當有一個類被不同的classloader載入時,這時要根據各自 loader下的instance數量判斷哪個loader更重要,從而要把另一個回收掉;
4,分析執行緒,本身heap dump裡包含了thread資訊,可以通過MAT來檢視threads 的overview和detail,detail中有執行緒的堆記憶體資訊,也有執行緒棧,同時還包含了作業系統本地棧。假設不做heap dump,我們檢查到系統有問題,如何通過執行緒的角度來排查呢?首先top -H -p <pid>以執行緒的模式檢視java應用的執行情況,找到佔用cpu或者記憶體大的執行緒,記錄執行緒id,然後printf %x <tid>轉為16進位制,再jstack -l <pid> > thread.log把java程式的thread dump出來,從裡面找到tid,分析是哪個執行緒佔用了系統資源。
5,分析java容器類,因為java的容器類是最常用來儲存物件的,所以理論上發生記憶體洩露的風險也最高。可以從幾個角度來 看:1)array填充率查詢(填充率fill ratio是陣列中非空元素的比例),列印非原生型別陣列的填充率頻率分佈,從而排查系統中array的利用率;2)陣列按照size分組查詢,列印一個 按size分組的直方圖;3)collection的填充率查詢,ArrayList/HashMap/Hashtable/Properties /Vector/WeakHashMap/ConcurrentHashMap$Segment;4)collection按照size分組直方圖;5) 檢視一個list裡的所有物件;6)檢視hashmap裡的所有物件;7)檢視hashset裡的物件;8)檢查map的碰撞率;9)檢查所有隻有一個常 量的array。
6,分析Finalizer,1)查詢finalizer正在處理的物件;2)查詢finalizer準備處理的物件;3)直接檢視finalizer執行緒;4)檢視finalizer執行緒的thread local物件。
相關文章
- Android記憶體優化(五)詳解記憶體分析工具MATAndroid記憶體優化
- eclipse Memory Analyzer(MAT) 記憶體分析Eclipse記憶體
- Java直接(堆外)記憶體使用詳解Java記憶體
- Mat使用詳解
- MAT工具定位分析Java堆記憶體洩漏問題方法Java記憶體
- Java記憶體管理原理及記憶體區域詳解Java記憶體
- Linux記憶體使用詳解Linux記憶體
- Java中的記憶體模型詳解Java記憶體模型
- [貝聊科技]使用Android Studio和MAT進行記憶體洩漏分析Android記憶體
- Java 物件記憶體分析Java物件記憶體
- Java記憶體分析一Java記憶體
- 程式執行過程記憶體分析詳解記憶體
- Java物件導向記憶體分析詳解(例項、圖)通俗易懂Java物件記憶體
- 利用MAT分析JVM記憶體問題,從入門到精通(二)JVM記憶體
- 圖文詳解Java物件記憶體佈局Java物件記憶體
- JVM系列之Java記憶體結構詳解JVMJava記憶體
- Java記憶體模型最全詳解(5大模型圖解)Java記憶體大模型圖解
- JAVA 記憶體洩露詳解(原因、例子及解決)Java記憶體洩露
- jvm(四)——JVM自帶記憶體分析工具詳解JVM記憶體
- 堆記憶體和棧記憶體詳解(轉載)記憶體
- JVM記憶體模型詳解JVM記憶體模型
- JVM堆記憶體詳解JVM記憶體
- iOS記憶體管理詳解iOS記憶體
- Java虛擬機器記憶體區域詳解Java虛擬機記憶體
- Java記憶體溢位的詳細解決方案Java記憶體溢位
- [轉帖]記憶體分析之GCViewer詳細解讀記憶體GCView
- Linux 使用記憶體分析Linux記憶體
- JVM記憶體分析工具使用JVM記憶體
- 【記憶體管理】Oracle AMM自動記憶體管理詳解記憶體Oracle
- Java陣列(基本+記憶體分析)Java陣列記憶體
- java陣列的記憶體分析Java陣列記憶體
- JVM面試問題系列:深入詳解JVM 記憶體區域及記憶體溢位分析JVM面試記憶體溢位
- Android記憶體優化(六)LeakCanary使用詳解Android記憶體優化
- iOS Memory 記憶體詳解 (長文)iOS記憶體
- 九、JVM記憶體模型詳解JVM記憶體模型
- Apache Spark 記憶體管理詳解ApacheSpark記憶體
- 使用 mtrace 分析 “記憶體洩露”記憶體洩露
- Java記憶體模型深度解讀Java記憶體模型