1.我們首先需要獲取當前java進程的pid。方法爲:
//查看當前進程pid
private static void getPID(){
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
String name = runtime.getName();
System.out.println("當前進程的標識爲:"+name);
int index = name.indexOf("@");
if (index != -1) {
int pid = Integer.parseInt(name.substring(0, index));
System.out.println("當前進程的PID爲:"+pid);
}
}
假設該進程pid爲8643
windows下執行命令:taskkill /pid 8436 /f 來強制終止該pid進程。
linux下執行:kill-9 8643來強制終止該pid進程
2.導出jvm中內存信息
jmap -dump:format=b,file=文件名 [pid]
3.java方法調用shell命令
String cmds = "jmap -dump:format=b,file=e:/jmap/"+System.currentTimeMillis()+".hprof "+pid;
Process pro = Runtime.getRuntime().exec(cmds);
pro.waitFor();
in = pro.getInputStream();
BufferedReader read = new BufferedReader(new InputStreamReader(in));
String result = read.readLine();
System.out.println(result);
上述代碼就可以將制定pid的java進程的dump文件以文件的形式輸出到制定目錄下。
問題:在cmds命令中,hprof與pid之間一定要有空格。
4.有些linux系統可能不能執行jmap命令:此時需要yum安裝即可。
yum install java-1.8.0-openjdk-devel-debug
5.輸出的java dump文件格式是.hprof格式的。我們需要特定的工具才能解析。
這裏推薦MAT(Eclipse的一種插件)。官網下載地址如下,下載完解壓即可。
MAT是有兩種安裝方式的,這一點與其他eclipse插件略有不同。
一種安裝方式是將MAT當做eclipse的插件進行安裝:啓動Eclipse –> Help –> Eclipse Marketplace,然後搜索Memory Analyzer,安裝,重啓eclipse即可。
另外一種安裝方式是將MAT作爲一個獨立的軟件進行安裝:去官網http://www.eclipse.org/mat/downloads.php,根據操作系統版本下載最新的MAT。下載後解壓就可以運行了。
修改MAT配置:
MAT 軟件版本解壓後目錄內有個MemoryAnalyzer.ini文件,該文件裏面有個Xmx參數,該參數表示最大內存佔用量,默認爲1024m,根據堆轉儲文件大小修改該參數即可。
1. MemoryAnalyzer.ini中的參數一般默認爲-vmargs– Xmx1024m,這就夠用了。假如你機器的內存不大,改大該參數的值,會導致MemoryAnalyzer啓動時,報錯:Failed to create the Java Virtual Machine。
2.當你導出的dump文件的大小大於你配置的1024m(說明1中,提到的配置:-vmargs– Xmx1024m),MAT輸出分析報告的時候,會報錯:An internal error occurred during: “Parsing heap dump from XXX”。適當調大說明1中的參數即可。
執行MemoryAnalyzer.exe打開軟件,然後打開file–openfile選擇前面生成的.hprof文件。就可以看到信息。如下圖。
在首頁上比較有用的是Histogram和Leak Suspects。
點擊Histogram,看到下圖:
點擊Leak Suspects會在堆轉儲文件同目錄內生成一個Leak Suspects.zip文件,同時也會從首頁跳轉到Leak Suspects頁面。
在Leak Suspects頁面會給出可能的內存泄露,如上圖所示有一個可能的內存泄露。這個問題是jar包或jdk裏面的,所以我們不用管。(因爲我這個生成.hprof文件並不是內存泄漏時生成的,而是爲了測試,強制生成的)
我們可以點擊 details進去查看詳細信息。
在詳情頁面Shortest Paths To the Accumulation Point表示GC root到內存消耗聚集點的最短路徑,如果某個內存消耗聚集點有路徑到達GC root,則該內存消耗聚集點不會被當做垃圾被回收。
在All Accumulated Objects by Class列舉了該對象所存儲的所有內容。