/ 前言 /
在講解Mat工具之前我們先來看下幾個關於Dump/文件的問題
-
Dump文件是什麼
Dump文件是進程的內存鏡像。可以把程序的執行狀態通過調試器保存到dump文件中
-
我們拿到Dump文件有什麼用的?
假如JVM因爲內存溢出的原因宕機了, 而程序的日誌裏面並沒有關於溢出所在對象的信息, 此時我們就需要通過分析Dump文件來找到問題原因
-
Dump文件怎麼生成?
-
第一種
在啓動JVM時指定參數
# 指定生成Dump文件的異常類型 -XX:+HeapDumpOnOutOfMemoryError # 指定Dump文件生成的位置 -XX:HeapDumpPath=/usr/local/jvm/dumps
-
第二種
如果你在啓動JVM時沒有指定參數, 那麼可以使用第二種方式來生成Dump文件, 使用JVM自帶的工具
jmap
jmap -dump:file=/usr/local/jvm/dumps/check.dump PID
PID的獲取可以通過
ps
|top
指令來獲取ps -ef|grep java top
-
/ 1 / 安裝Mat
Mat是Eclipse的一個插件, 也可以獨立運行, 所以即使你使用IDEA也可以獨立使用Mat
Mat官網下載地址
根據操作系統選擇對應的版本即可
下載下來是一個zip
壓縮包解壓即可
Mac解壓後是一個.app
, 直接運行會報錯
我們需要修改一下啓動方式或者將.app
文件移動到應用程序下
/Users/xxx/Downloads/mat.app/Contents/MacOS/MemoryAnalyzer -data ./workspace
啓動後的界面
啓動後在導入Dump文件時有可能會報錯
An internal error occurred during: "Parsing heap dump from 'xxx.dump'".
Java heap space
這是因爲Dump文件的大小超出了Mat默認的讀取範圍, 我們需要修改Mat的配置文件
找到MemoryAnalyzer.ini
文件
Windows/Linux中該文件就在解壓縮的目錄下
Mac中該文件在mat.app/Contents/Eclipse
下
-startup
../Eclipse/plugins/org.eclipse.equinox.launcher_1.5.0.v20180512-1130.jar
--launcher.library
../Eclipse/plugins/org.eclipse.equinox.launcher.cocoa.macosx.x86_64_1.1.700.v20180518-1200
-vmargs
-Xmx4g
-Dorg.eclipse.swt.internal.carbon.smallFonts
-XstartOnFirstThread
修改-Xmx
的值即可
/ 2 / Mat功能介紹
2 . 1 Overview
Dump文件信息, 使用餅狀圖的方式來展示內存佔用的信息
- Details是文件信息詳情, 包含了文件大小、字節碼文件大小、對象文件大小、類加載器數量
- Actions是常用的操作彙總, 與左上角的菜單功能相同
2 . 2 Histogram
Histogram彙總了使用到的類的對象數量以及堆佔用空間
我們還可以根據實際情況對Histogram展示的數據進行分類
在結果的第二行<Regex>
中我們可以進行模糊查詢
2 . 3 Dominator_Tree
Dominator_Tree彙總了堆內存空間中佔比最大的對象, 按照空間大小排序, 我們可以通點擊左邊的箭頭符號查看當前對象的引用狀況, 最右側爲當前對象所佔空間比例
2 . 4 OQL
OQL是Object Query Language的簡寫,即對象查詢語言, 語法與SQL類似, 點擊上方的紅色感嘆號開始執行
2 . 5 Thread_Overview
線程視圖, 彙總了Dump文件中所有線程的信息, 按照線程所佔用的空間進行排序
2 . 6 Leak Suspects
內存泄漏疑點, 這是Mat根據Dump文件的分析結果得到最有可能導致OOM的疑點, 也是我在使用Mat工具時第一個打開的工具
點擊Details查看詳細分析信息
2 . 7 Path to GC Roots & Merge Shortest Paths to GC Roots
研究這倆個工具之前我們需要先了解一下GC對不同引用關係之間的區別
2 . 7 . 1 GC對不同引用關係之間的區別
-
虛引用(PhantomReference)
虛引用無法決定一個對象的生命週期, 因爲持有虛引用的對象和沒有引用一樣, 隨時都會被GC回收, 且虛引用的使用必須搭配引用隊列一起使用PhantomReference
-
弱引用(WeakReference)
與虛引用相比擁有短暫的生命週期, 長短則取決於GC什麼時候回發現它, 需要搭配WeakReference
來使用 -
軟引用(SoftReference)
與弱引用相比, 軟引用的生命週期長短取決於堆內存是否充足, 如果堆內存已經滿了, 那麼GC就會回收軟引用對象 -
強引用(StrongReference)
我們平常創建對象時都是創建的強引用對象, 不論堆內存是否充足, 只要該對象還存在引用關係GC就不會回收, 這也是OOM異常的觸發原因
2 . 7 . 2 Path to GC Roots
當前對象到GC Root的路徑, 也就是當前對象的引用關係, 該工具只能展示單個對象的引用關係, 所以只能在Dominator_Tree
中使用
2 . 7 . 3 Merge Shortest Paths to GC Roots
一組對象到GC Root的最短路徑, 效果與Path to GC Roots
相同, 可以在Histogram
中使用
選擇一條數據點擊右鍵並選擇Path To GC Roots, 選擇展示結果排除需引用、弱引用、軟引用, 我們只需要看強引用即可