Java:尽管有足够的可分配内存,但“超出了GC开销限制”

时间:2012-12-29 01:13:23

标签: java garbage-collection

我不明白如何获得此异常,而JVM使用的总内存(Runtime.totalMemory())大约是可分配的一半(Runtime.maxMemory())。有什么想法吗?

Total Memory : 1708MB as returned by Runtime.getRuntime().totalMemory() 
Max. Memory  : 3545MB as returned by Runtime.getRuntime().maxMemory() 

JRE : Java HotSpot(TM) 64-Bit Server VM  :  1.6.0_29   (Linux)

1 个答案:

答案 0 :(得分:1)

正如pcalcao所提到的,JVM告诉你它在垃圾收集上花费了太多时间,并且没有做足够的实际工作,所以它只会挽救。

这是一种安全阀,可以避免您实际上没有内存耗尽,但足够接近以至于您确实没有取得任何进展。我不会强调这一点 - this answer有更多细节,但我会提到一些可能适用于你案件的事情:

如果您SoftReference要缓存内容,则更有可能发生这种情况 - 当堆增长到最大大小时,这些引用会被清除并可能重复重新生成(取决于您的密钥循环是否接触)它们,结果在GC不断发生的一些不良行为中,总是恢复足够的内存以继续运行,因为它能够清除一些软引用 - 甚至JDK也会因为它们在Locale类中使用这种缓存而受此影响。

如果您真的想使用-XX,可以禁用此行为:-UseGCOverheadLimit。尽管如此,它表明的问题仍然存在 - 您花费的时间不到运行时间的2%。

你在哪里打印出那些记忆值?根据程序的结构,它可能会产生大量垃圾并在一些内部循环中使用大部分堆,但是在放置诊断输出的地方,垃圾被回收。 -verbose:gc可以更好地描述实际的GC行为。