操做系統:ubuntu 14.04php
IDE:Eclipse Java EE IDE for Web Developers. Version: Luna Service Release 2 (4.4.2)java
JDK版本:1.7.0_80linux
MAT版本:1.5.0程序員
最近經過公司的哨兵監控系統發現個人項目內存使用率天天都會增長一點,以下圖。對於一個穩定運行的java項目而言,出現這種狀況通常都有多是出現了內存泄露。ubuntu
MAT是有兩種安裝方式的,這一點與其餘eclipse插件略有不一樣。瀏覽器
一種安裝方式是將MAT當作eclipse的插件進行安裝:啓動Eclipse --> Help --> Eclipse Marketplace,而後搜索Memory Analyzer,安裝,重啓eclipse便可。服務器
另一種安裝方式是將MAT做爲一個獨立的軟件進行安裝:去官網http://www.eclipse.org/mat/downloads.php,根據操做系統版本下載最新的MAT。下載後解壓就能夠運行了。eclipse
我使用的是MAT 1.5 linux x64 版本。MAT不一樣版本按鍵位置或功能可能會有不一樣。ui
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中的參數便可。spa
獲取堆轉儲文件我嘗試過兩種方式
第一種方式是採用jamp獲取,對於部署到服務器上的程序能夠採用這種方式,獲取堆轉儲文件後scp到本地,而後本地分析。獲取命令爲:
這種方式得到的堆轉儲文件只能在MAT軟件中打開,安裝了插件的eclipse沒有相應的打開選項。
另外一種方式是在eclipse中安裝mat插件,運行程序,File --> new --> Other --> Heap Dump --> next ,選擇對應的進程, Finish。這種方式彷佛對遠程服務器上的程序也能夠,沒有深刻研究。此種方式得到堆轉儲文件後eclipse會默認打開,以下圖所示,選擇Leak Suspects Report, Finish就能夠進入MAT分析頁面的首頁。
我在實際操做過程當中採用的是jmap獲取堆轉儲文件,而後scp到本地,而後MAT軟件加載。
加載後首頁以下圖,在首頁上比較有用的是Histogram和Leak Suspects。
點擊Leak Suspects會在堆轉儲文件同目錄內生成一個Leak Suspects.zip文件,同時也會從首頁跳轉到Leak Suspects頁面。
解壓該文件後能夠經過瀏覽器打開分析結果。
下面是Leak Suspects頁面
在Leak Suspects頁面會給出可能的內存泄露,如上圖所示有三個可能的內存泄露,可是隻有第一個是我程序裏的,另外兩個是jar包或jdk裏面的,這個能夠不用管。
點擊Details進入詳情頁面。在詳情頁面Shortest Paths To the Accumulation Point表示GC root到內存消耗匯集點的最短路徑,若是某個內存消耗匯集點有路徑到達GC root,則該內存消耗匯集點不會被當作垃圾被回收。
在All Accumulated Objects by Class列舉了該對象所存儲的全部內容。
爲了找到內存泄露,我獲取了兩個堆轉儲文件,兩個文件獲取時間間隔是一天(由於內存只是小幅度增加,短期很難發現問題)。對比兩個文件的對象,經過對比後的結果能夠很方便定位內存泄露。
MAT同時打開兩個堆轉儲文件,分別打開Histogram,以下圖。在下圖中方框1按鈕用於對比兩個Histogram,對比後在方框2處選擇Group By package,而後對比各對象的變化。不難發現heap3.hprof比heap6.hprof少了64個eventInfo對象,若是對代碼比較熟悉的話想必這樣一個結果是可以給程序員必定的啓示的。而我也是根據這個啓示差找到了最終內存泄露的位置。
我內存泄露位置是一個list,這個list只在這裏一直不停的往裏添加eventInfo對象,卻沒有釋放過。
修改後代碼: