您好,登錄后才能下訂單哦!
本篇內容介紹了“如何使用JVM內存分析工具MAT”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
MAT 是一款非常強大的內存分析工具,在 Eclipse 中有相應的插件,同時也有單獨的安裝包。在進行內存分析時,只要獲得了反映當前設備內存映像的 hprof
文件,通過 MAT 打開就可以直觀地看到當前的內存信息。
下載獨立版本的 MAT,下載地址:https://www.eclipse.org/mat/downloads.php,下載后解壓。找到 MemoryAnalyzer.ini
文件,該文件里面有個 Xmx 參數,該參數表示最大內存占用量,默認為 1024m,根據堆轉儲文件大小修改該參數即可。
堆轉儲文件(Heap Dump)是 Java 進程在某個時間內的快照(.hprof 格式)。它在觸發快照的時候保存了很多信息,如:Java 對象和類信息(通常在寫堆轉儲文件前會觸發一次 Full GC)。
堆轉儲文件信息:
所有的對象信息,包括對象實例、成員變量、存儲于棧中的基本類型值和存儲于堆中的其他對象的引用值。
所有的類信息,包括 classloader、類名稱、父類、靜態變量等。
GC Root 到所有的這些對象的引用路徑。
線程信息,包括線程的調用棧及此線程的線程局部變量(TLS)。
多種方式獲取堆轉儲文件:
通過 jmap 命令可以在 cmd 里執行:jmap -dump:format=b,file=<文件名.hprof> <pid>
。
如果想在發生內存溢出的時候自動 dump,需要添加下面 JVM 參數:-XX:+HeapDumpOnOutOfMemoryError
。
使用 Ctrl+Break 組合鍵主動獲取獲取,需要添加下面 JVM 參數:-XX:+HeapDumpOnCtrlBreak
。
使用 HPROF Agent 可以在程序執行結束時或受到 SIGOUT 信號時生成 Dump 文件,配置在虛擬機的參數如下:-agentlib:hprof=heap=dump,format=b
。
使用 JConsole 獲取。
使用 Memory Analyzer Tools 的 File -> Acquire Heap Dump
功能獲取。
打開 MAT 之后,加載 dump 文件,差不多就下面這樣的界面:
常用的兩個功能:Histogram、 Leak Suspects
。
Histogram 可以列出內存中的對象,對象的個數及其內存大小,可以用來定位哪些對象在 Full GC 之后還活著,哪些對象占大部分內存。
Class Name:類名稱,Java 類名。
Objects:類的對象的數量,這個對象被創建了多少個。
Shallow Heap:對象本身占用內存的大小,不包含其引用的對象內存,實際分析中作用不大。常規對象(非數組)的 Shallow Size 由其成員變量的數量和類型決定。數組的 Shallow Size 由數組元素的類型(對象類型、基本類型)和數組長度決定。對象成員都是些引用,真正的內存都在堆上,看起來是一堆原生的 byte[], char[], int[],對象本身的內存都很小。
Retained Heap:計算方式是將 Retained Set(當該對象被回收時那些將被 GC 回收的對象集合)中的所有對象大小疊加。或者說,因為 X 被釋放,導致其它所有被釋放對象(包括被遞歸釋放的)所占的 heap 大小。Retained Heap 可以更精確的反映一個對象實際占用的大小。
Retained Heap 例子:一個 ArrayList 對象持有 100 個對象,每一個占用 16 bytes,如果這個 list 對象被回收,那么其中 100 個對象也可以被回收,可以回收 16*100 + X 的內存,X 代表 ArrayList 的 shallow 大小。
在上述列表中選擇一個 Class,右鍵選擇 List objects > with incoming references
,在新頁面會顯示通過這個 class 創建的對象信息。
繼續選擇一個對象,右鍵選擇 Path to GC Roots > ****
,通常在排查**內存泄漏(一般是因為存在無效的引用)**的時候,我們會選擇 exclude all phantom/weak/soft etc.references
,意思是查看排除虛引用/弱引用/軟引用等的引用鏈,因為被虛引用/弱引用/軟引用的對象可以直接被 GC 給回收,我們要看的就是某個對象否還存在 Strong 引用鏈(在導出 Heap Dump 之前要手動觸發 GC 來保證),如果有,則說明存在內存泄漏,然后再去排查具體引用。
這時會拿到 GC Roots 到該對象的路徑,通過對象之間的引用,可以清楚的看出這個對象沒有被回收的原因,然后再去定位問題。如果上面對象此時本來應該是被 GC 掉的,簡單的辦法就是將其中的某處置為 null 或者 remove 掉,使其到 GC Root 無路徑可達,處于不可觸及狀態,垃圾回收器就可以回收了。反之,一個存在 GC Root 的對象是不會被垃圾回收器回收掉的。
Leak Suspects 可以自動分析并提示可能存在的內存泄漏,可以直接定位到 Class 及對應的行數。
比如:這里問題一的描述,列出了一些比較大的實例。點擊 Details
可以看到細節信息,另外還可點擊 See stacktrace
查看具體的線程棧信息(可直接定位到具體某個類中的方法)。
在 Details 詳情頁面 Shortest Paths To the Accumulation Point
表示 GC root 到內存消耗聚集點的最短路徑,如果某個內存消耗聚集點有路徑到達 GC root,則該內存消耗聚集點不會被當做垃圾被回收。
實戰:在某項目中,其中幾個 Tomcat 響應特別慢,打開
Java VisualVM
觀察Tomcat(pid xxx)-Visual GC
發現Spaces-Old
升高,Graphs-GC Time
比較頻繁且持續時間長、有尖峰(重啟后過段時間又出現了),最后通過Leak Suspects
中的See stacktrace
定位到某個查詢接口,仔細排查代碼后發現有個 BUG:在特定查詢條件下會一次性查詢幾萬的數據出來(因為臟數據),處理過后恢復正常。
為了更有效率的找出內存泄露的對象,一般會獲取兩個堆轉儲文件(先 dump 一個,隔段時間再 dump 一個),通過對比后的結果可以很方便定位。
“如何使用JVM內存分析工具MAT”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。