天天看點

記憶體洩露的解決方法

分析記憶體洩露的一般步驟

  1. 把Java應用程式使用的heap dump下來
  2. 使用Java heap分析工具,找出記憶體占用超出預期(一般是因為數量太多)的嫌疑對象
  3. 必要時,需要分析嫌疑對象和其他對象的引用關系。
  4. 檢視程式的源代碼,找出嫌疑對象數量過多的原因。

一、dump檔案擷取

jmap -dump:format=b,file=檔案名 [pid]
           

二、下載下傳Java heap分析工具,這裡使用Memory Analyse Tool,用免費的沒錯

下載下傳位址是:http://www.eclipse.org/mat/downloads.php

在MemoryAnalyzer.ini檔案,修改MAT可用記憶體,需要dump檔案大。調整-Xmx屬性,預設是1024M,我給改成了3024M。

三、加載dump檔案

點選File–>Open Heap Dump,選擇dump檔案,MAT會加載并分析該dump檔案,如果檔案較大,可能需要一些時間。

開始分析時可以選擇是否分析可能存在的問題,如果選擇是,MAT會提供Problem Suspect,這個Problem Suspect如果你切到别的标簽再切回來就沒有了,可以通過點選Leak Suspects連結重新獲得。Problem Suspect1和Problem Suspect2表示兩個可疑對象,Remainder表示其它對象。

記憶體洩露的解決方法

四、分析dump檔案結果

1.向下拉動界面,展示了一些分析結果,表示3728個Configuration對象被HashMap引用。

3,728 instances of "org.apache.hadoop.conf.Configuration", loaded by "org.apache.catalina.loader.ParallelWebappClassLoader @ 0x6c00717c0" occupy 411,961,384 (31.76%) bytes. These instances are referenced from one instance of "java.util.HashMap$Node[]", loaded by "<system class loader>"

Keywords
org.apache.hadoop.conf.Configuration
org.apache.catalina.loader.ParallelWebappClassLoader @ 0x6c00717c0
java.util.HashMap$Node[]
           

2.再點選下面的類引用圖,點選HashMap對象,檢視左上角該對象的一些概要資訊。發現key是FileSystem C a c h e Cache CacheKey,value是DistributedFileSystem

記憶體洩露的解決方法

3.查到這裡我們就可以分析自己的代碼,為什麼引用了這麼多對象。如果引用裡面直接定位到問題行,事情就好辦了。但我這裡的案例沒法直接定位到工程問題行,DistributedFileSystem是hadoop HDFS的類。我就google搜尋了hdfs FileSystem記憶體洩露,果然有類似的問題。最後定位發現是有些代碼fs沒有關閉,導緻fs緩存不斷累積,最後導緻記憶體溢出。也算填了前人的坑。總之要善用搜尋引擎,如果搜尋不到,也隻能一步步分析調試源碼了。