2012-11-07 19 views
1

我有一個應用程序在後臺使用java線程池執行一些繁重的處理。OutOfMemoryError具有可用內存

線程池被配置爲記錄異常的執行

public enum ExceptionLogger implements Thread.UncaughtExceptionHandler { 
    INSTANCE; 

    private static final Logger log = LoggerFactory.getLogger(ExceptionLogger.class); 

    @Override 
    public void uncaughtException(Thread t, Throwable e) { 
     log.error("Exception occurred at thread " + t.getName() + "\n", e); 
    } 
    } 

在我的應用程序的日誌,我隨機得到java.lang.OutOfMemoryError: Java heap space但如果我登錄使用Runtime.getRuntime().freeMemory()內存使用情況,我可以看到很多免費的堆空間時發生可用。

此外,我得到這個異常後應用程序繼續工作。

是否有任何其他原因使此消息變得OutOfMemoryError

回答

3

當內存分配失敗時,您將收到OutOfMemoryError。

就會發生這種情況時

  • 你已經耗盡內存。
  • 您的GC轉動參數阻止它使用所有內存。例如爲未滿的世代設置最小尺寸。
  • 你分配一大塊內存。緊接着失敗後,你仍然有空閒的內存,只是不足以分配大塊。
  • 你會得到一個不適合堆的OutOfMemoryError,例如PermGen或直接內存或虛擬內存(針對線程等)
+0

+1 - 另一種情況是當新線程堆棧沒有足夠內存時。 –

+0

我認爲虛擬內存不足,但也可能缺少交換空間。 –

+1

另一種可能性是你的堆堆滿了無法訪問的對象,因爲至少有一個線程持有「GC鎖定器」互斥鎖(當例如JNI代碼使用GetPrimitiveArrayCritical時,它保留着)。當鎖被鎖定時,Hotspot似乎從不執行任何GC。 –

1

除了Peter Lawrey的出色答案外,您還有「達到GC開銷限制」錯誤。

當JVM沒有足夠的處理時間來進行垃圾收集或GC佔用了太多的總可用處理能力時,會發生這種情況。主要是當你有大量非常短暫的對象與CPU飢餓的應用程序結合並且沒有足夠的平均空閒堆(最大堆大小 - 長壽命對象)時。

解決方案有所不同,但通常意味着您必須限制CPU消耗(對於您的情況,線程數量)和/或增加堆大小。

相關問題