2011-08-24 77 views
8

我在我的應用程序中遇到臭名昭着的OutOfMemoryException,而不是簡單地增加可用的堆空間量,而是試圖查看問題的原因,以防萬一,從我的應用程序中出現某種泄漏。Java堆空間 - -Xmx如何工作?

我添加了JVM參數-XX:+ HeapDumpOnOutOfMemoryError它在遇到OutOfMemory錯誤時創建堆轉儲。然後我分析了使用不同分析工具生成的轉儲文件。然後我開始玩弄-Xmx參數並觀察模式。

讓我感到困惑的是以下幾點。爲什麼在分析轉儲時,我發現所有對象的總大小遠遠小於使用-Xmx參數設置的總大小?例如,假設我將-Xmx設置爲'2048m'。當我分析轉儲文件時,我在堆上發現了總共400Mb的對象。我期待找到2GB。我錯過了什麼嗎?

+0

你是否檢查過你的OOME實際上提到了堆內存?有幾個(相對不常見的)OOME被拋出的情況,但它不是堆滿了。 –

+1

對,@Joachim,JVM x86中的線程太多,OOM異常也崩潰 – aalku

回答

3

重新讀取您的錯誤消息 - 它可能會告訴您哪種類型的內存用完了。我猜想這是PermGen的空間。 Permgen用於類定義(除其他外)。您可以通過-XX調整PermGen的空間:MaxPermSize PermGen不是堆的一部分,所以不包含在堆轉儲中。

有關查看PermGen的更多信息,請參閱this answer

如果這不是問題,那麼嘗試將初始堆大小(-Xms)設置爲與最大值相同。這樣做意味着堆不會增長,應該更容易理解正在發生的事情。

我建議使用jvisualvm(JDK的一部分)來查看程序運行時的內存利用率。

+0

可能很有趣....是的,我得到的錯誤是這一個。試着知道。將回來的結果。 – Kros

+0

使用了-XX:MaxPermSize,並且自那時以來一直存在問題。我認爲,我的應用程序的最新變化導致超出了閾值,導致了例外。謝謝你的幫助。 – Kros

5

我的猜測是,由於現代GC將堆分成單獨的內存區域(年輕/終身/永久代),永久生成空間足以滿足發生內存不足的錯誤。您可以使用各種JVM命令行選項來配置不同生成空間的比例。

這是一篇關於Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine的好文章(我找不到更新的文章,但我認爲基礎知識仍然適用於更新的虛擬機)。