一次排查Java專案記憶體洩漏的過程

爆米花機槍手發表於2018-08-17

發現問題

公司自己維護的服務三四個,有的服務還分多個節點,自己也有幾個私人伺服器,所以為了能實時知道各個伺服器的情況,就使用ServerStatus做了個雲探針,功能很簡單,能實時的監控每個伺服器的記憶體、cpu、硬碟、流量的使用情況,如下
實時監控圖
雖然只有幾個指標,但是已經能讓我全面的掌握各服務的效能,再搭配chrome外掛iChrome,每天開啟瀏覽器就能第一時間看到監控介面,
iChrome.png
我始終相信一句話:

工欲善其事必先利其器

最近一段時間,我發現我的一個服務所在的兩臺伺服器記憶體處於不停的增長狀態,8g記憶體,直接超過65%,這讓我很鬱悶,為什麼會醬紫,就在昨天,我在一個伺服器上做測試(不是普通的測試,而是去驗證某正邏輯線上上是否正確的測試),然後整個服務直接當機了,趕緊找公司的運維人員(你可能會問既然公司有運維,為什麼還要自己搗鼓監控,我想說,作為一個開發,最好能在第一時間發現任何問題,還有一句話“求人不如求幾”)看下伺服器當機前的狀態,果然是記憶體突然暴增,所以我就很有必要去找出導致服務記憶體持續增長原因。

jmap

網上找了一些命令,感覺jmap最好用

命令列輸入:jmap -histo <pid> | head -20,就可以檢視某個pid的java服務佔用記憶體排名前20的類。注:該命令不適用於Windows系統裡

jmap -dump:format=b,file=filename.bin <pid>, 將整個記憶體情況儲存到檔案裡,然後匯出使用MAT(Memory Analyse Tool)分析
注意:堆轉儲檔案可能比較大,我的有2.5個G

MAT

Memory Analyse Tool 記憶體分析工具,直接下載,下載解壓之後,可以修改下配置檔案MemoryAnalyzer.ini,修改裡面的引數如-Xmx5120m(最好要大於你的堆轉儲檔案)

然後將堆轉儲檔案匯入進去就可以了
微信截圖_20180817134945.png

點選“Leak Suspects”一般會顯示MAT它自己認為有問題的內容,如下
微信截圖_20180817135050.png
同時會在堆轉儲檔案的同級目錄下生成一個壓縮檔案filename_Leak_Suspects.zip,裡面是一個html靜態頁面,我們也可以在瀏覽器去分析

點選“Accumulated Objects in Dominator Tree”
就可以看到問題所在了
微信截圖_20180817135301.png
發現WordDictionary中HashMap的數量異常,然後一層一層的網上找,發現了這句程式碼

public class xxx {
    private JiebaSegmenter segmenter = new JiebaSegmenter(); // 分詞
}

然而專案裡對這個xxx類依賴較多,每次使用xxx的時候,都要重新去建立JiebaSegmenter物件。。。。
趕緊將其改為

    private static JiebaSegmenter segmenter = new JiebaSegmenter(); // 分詞

因為這個分詞程式是直接在github上面找的程式碼,所以沒有認真去看,真的是應了那句話“該來的遲早會來~~~”

最後

以上就是自己通過記憶體分析定為到具體程式碼的整個過程,之類MAT用的很簡單,只是簡單的分析,也可以參考這篇https://blog.csdn.net/wanghuiqi2008/article/details/50724676,整個過程很順暢,當然了還需要對自己程式碼非常熟才行,否則半天都不會定位到問題。

今天是七夕,祝各位程式設計師早早下班,陪女友吃好喝好玩好為愛鼓掌到天明~~~~

相關文章