2016-06-07 64 views
1

我是新來分析Java中的內存問題。所以,原諒我,如果這個問題似乎幼稚JVM堆沒有發佈

我的應用程序有以下JVM參數設置運行:

-Xms3072m -Xmx3072m 
-XX:MaxNewSize=1008m -XX:NewSize=1008m 
-XX:PermSize=224m -XX:MaxPermSize=224m -XX:SurvivorRatio=6 

我使用VisualVM的監視的使用情況:以下是我看到

enter image description here

問題是,即使應用程序沒有收到任何要處理的數據,使用的內存也不會關閉。當應用程序啓動時,已用空間開始很低(大約1GB),但隨着應用程序的運行而增長。然後使用的內存永遠不會下降。 我的問題是爲什麼即使在應用程序中沒有發生重大的處理以及可以設置哪些配置來糾正它時,使用的堆內存也不會停止運行。 我的理解是,如果應用程序沒有進行任何處理,那麼在這種情況下,使用的堆應該更少,可用的堆內存(或最大堆)應該保持不變(3GB)。

+0

你的意思是最大堆大小? –

+1

你爲什麼認爲它應該下降? –

+0

查看其他答案/評論,但是如果確實有內存泄漏,請創建堆轉儲並使用eclipse MAT進行分析。 http://www.eclipse.org/mat/ – OldProgrammer

回答

4

這是一個完全正常的趨勢,即使您認爲它沒有被使用,也可能有線程在執行任務,創建一個對象,一旦任務完成後,這些對象可以用於下一個GC,但只要因爲沒有minor/major GC它們會佔用越來越多的空間,所以它會一直持續到GC被觸發,然後你會得到正常的堆大小,等等。

一個不正常的趨勢將是同樣的事情,但在一個GC之後,堆大小將高於前一個GC之後的堆大小,在這裏不是這種情況。

你真正的問題是什麼,當我沒有收到任何數據處理我的應用程序正在做什麼?爲此,線程轉儲應該有所幫助,您可以啓動jcmd以獲取PID,然後啓動jstack $pid以獲取線程轉儲。

下面是一個典型的趨勢在內存泄漏的情況下的實例:

enter image description here

正如你可以看到起始堆大小有兩個GC之間改變,則新的起始堆大小比更高前一個可能是由於內存泄漏。

+0

感謝您的回覆。我會檢查線程轉儲。另一個問題是,如果GC正在運行,爲什麼堆大小仍然沒有下降。或者是主要/次要GC未運行? (我不認爲這是可能的,因爲JVM會運行GC)。我怎樣才能驗證這一點? – mehta

+0

調用從JVisual VM執行GC以觸發主要的GC,剩餘的堆大小是應用程序當前的內存足跡,由未被未引用的對象組成,因爲它們仍然由應用程序使用。 –

+0

明白了。事實上,我只注意到,只要使用過的內存觸摸3 GB(最大可用大小),就會執行GC活動並使用內存降至1 GB。 – mehta