如何診斷 Java 中的記憶體洩露

ImportNew發表於2015-12-04

每次我懷疑有記憶體洩漏時,我都要翻箱倒櫃找這些命令。所以,這裡總結一下以備後用:

首先,我用下面的命令監視程式:

while ( sleep 1 ) ; do ps -p $PID -o %cpu,%mem,rss  ; done

(如果有的話還有New Relic)

如果你看到記憶體上升很快,可能是因為虛擬機器設定。如果你沒有明確指定JVM的記憶體設定,它將設定預設值給他們。要獲得預設值,使用以下命令:

java -XX:+PrintFlagsFinal -version | grep -i HeapSize

如果這些都不符合你所希望的,那麼你就需要指定JVM的記憶體設定。可以用下面的命令設定最小和最大堆大小:

java -Xms128m -Xmx256m

儘管你有了合理的記憶體設定,也可以監控程式,但你仍然可能看到記憶體隨時間增加。為了進一步探究原因,你可以使用下面的命令檢視物件例項的直方圖:

jmap -histo $PID

如果仍然沒有足夠的資訊,那麼可以用以下命令進行堆轉儲:

jmap -dump:format=b,file=/tmp/dump1.hprof $PID

通常,我會用兩個堆轉儲,然後使用下面的jhat命令比較它們:

jhat -baseline /tmp/dump1.hprof /tmp/dump2.hprof

這個命令會啟動一個HTTP伺服器,你可以用它來探索這兩個堆轉儲之間的差值。在預設情況下,HTTP伺服器啟動7000埠,你可以在瀏覽器中訪問該埠。

如果你有防火牆,可以通過SSH訪問,那麼你可以通過如下命令連線該埠:

ssh -L 7000:localhost:7000 $HOST

向下滾動到第一頁的底部,你會看到兩個有用的連結:

這將給你展示在不同堆轉儲之間所有“新”的例項,應該對你檢測洩漏來自哪裡有些幫助。截圖如下:

診斷Java中的記憶體洩露

然後你就擁有了一個神奇命令列的快速檢視目錄,以便於你需要診斷記憶體洩漏時使用(然而我總是忘記)。

相關文章