原文地址:http://gao-xianglong.iteye.com/blog/2173140?utm_source=tuicool&utm_medium=referral
前言
生產環境中,尤其是吃大內存的JVM,一旦出現內存泄露等問題是非常容易引發OutofMemory的,如果沒有一個好的工具提供給開發人員定位問題和分析問題,那么這將會是一場噩夢。目前JDK其實自帶有一些內存泄露分析工具專門用於幫助開發人員定位內存泄露等問題,但是這些工具往往並不是能夠滿足一些現狀,這里筆者所指的現狀更多是迅速、便捷、高效的定位出問題,方便開發人員迅速進行調整。
目錄
一、使用jmap工具生成dump文件
二、MAT工具的下載和安裝
三、使用MAT工具進行內存泄露分析
一、使用jmap工具實現堆轉儲、
jmap是什么?簡單來說,jmap是JDK自帶的一種用於生成內存鏡像文件的工具,通過該工具,開發人員可以快速生成dump文件。開發人員可以使用命令“jmap -help”查看jmap的常用命令,如下所示:
- Usage:
- jmap [option] <pid>
- (to connect to running process)
- jmap [option] <executable <core>
- (to connect to a core file)
- jmap [option] [server_id@]<remote server IP or hostname>
- (to connect to remote debug server)
- where <option> is one of:
- <none> to print same info as Solaris pmap
- -heap to print java heap summary
- -histo[:live] to print histogram of java object heap; if the "live"
- suboption is specified, only count live objects
- -permstat to print permanent generation statistics
- -finalizerinfo to print information on objects awaiting finalization
- -dump:<dump-options> to dump java heap in hprof binary format
- dump-options:
- live dump only live objects; if not specified,
- all objects in the heap are dumped.
- format=b binary format
- file=<file> dump heap to <file>
- Example: jmap -dump:live,format=b,file=heap.bin <pid>
- -F force. Use with -dump:<dump-options> <pid> or -histo
- to force a heap dump or histogram when <pid> does not
- respond. The "live" suboption is not supported
- in this mode.
- -h | -help to print this help message
- -J<flag> to pass <flag> directly to the runtime system
在此大家需要注意,jmap工具有一部分命令僅限於Linux和Solaris平台,而Windows平台下能夠使用的命令只有“jmap -histo<pid>”和“jmap -dump:<dump-options><pid>”。不過一般來說,使用命令“jmap -dump:<dump-options><pid>”生成dump文件應該是最常用的命令之一,由於生成dump文件時比較耗時的,因此大家需要耐心等待,尤其是大內存鏡像生成dump文件則需要耗費更長的時間來完成。
二、MAT工具的下載和安裝
MAT(Memory Analyzer Tool)工具是eclipse的一個插件,使用起來非常方便,尤其是在分析大內存的dump文件時,可以非常直觀的看到各個對象在堆空間中所占用的內存大小、類實例數量、對象引用關系、利用OQL對象查詢,以及可以很方便的找出對象GC Roots的相關信息,當然最吸引人的還是能夠快速為開發人員生成內存泄露報表,方便定位問題和分析問題。
MAT工具的下載地址為:http://www.eclipse.org/mat/downloads.php
MAT插件的下載地址為:http://download.eclipse.org/mat/1.3/update-site/
筆者所使用的MAT工具的版本為最新的1.4.0,為了避免在實際使用過程中出現一些不必要的異常情況,筆者建議大家使用與筆者相同版本版本的MAT工具分析dump文件。
只要確保機器上成功裝有JDK並配置好相關的環境變量后,運行“MemoryAnalyzer-1.4.0.20140604-win32.win32.x86\mat\”目錄下的MemoryAnalyzer.exe即可成功啟動MAT工具。
三、使用MAT工具進行內存泄露分析
當大家成功下載和安裝好MAT后,接下來要做的事情就是使用jmap+MAT工具一起進行內存泄露工作的分析。首先筆者先准備一段測試代碼,如下所示:
- /**
- * -server -Xms1024m -Xmx1024m -Xmn384m -XX:+UseParallelOldGC
- * -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -XX:+PrintGCDetails
- * -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=c:/heap.bin
- */
- public class GCTest {
- public static void main(String[] args) {
- final int _1mb = 1024 * 1024;
- byte[] value1 = new byte[_1mb * 100];
- byte[] value2 = new byte[_1mb * 100];
- byte[] value3 = new byte[_1mb * 100];
- new Thread() {
- public void run() {
- byte[] value4 = new byte[_1mb * 400];
- }
- }.start();
- byte[] value5 = new byte[_1mb * 200];
- }
- }
在上述代碼示例中,具體的VM參見類注釋,而選項“-XX:+HeapDumpOnOutOfMemoryError ”和-“XX:HeapDumpPath”所代表的含義就是當程序出現OutofMemory時,將會在相應的目錄下生成一份dump文件,而如果不指定選項“XX:HeapDumpPath”則在當前目錄下生成dump文件。在此大家需要注意,盡管不借助jmap工具,MAT工具也能夠直接生成dump文件,但是考慮到生產環境中幾乎不可能在線對其進行分析,大都是采用離線分析,因此使用jmap+MAT工具是最常見的組合。
當上述程序執行時,必然會觸發OutofMemory,然后在所指定的目錄下找到生成的dump文件后,我們便可以通過MAT工具來進行分析了。當成功啟動MAT后,通過菜單選項“File->Open heap dump...”打開指定的dump文件后,將會生成Overview選項,如圖1-1所示:
圖1-1 Overview選項
在Overview選項中,以餅狀圖的形式列舉出了程序內存消耗的一些基本信息,其中每一種不同顏色的餅塊都代表了不同比例的內存消耗情況。如果說需要定位內存泄露的代碼點,我們可以通過Dominator Tree菜單選項來進行排查(MAT工具僅僅只是一個輔助,分析OutofMemory並不存在一個固定的方式和准則,因此仔細觀察和分析才能夠找到問題所在),如圖1-2所示:
圖1-2 Dominator Tree選項