4

我不明白如何在 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)
4

1 回答 1

1

正如 pcalcao 所提到的,JVM 告诉您它在垃圾收集上花费了太多时间,并且没有做足够的实际工作,所以它只是打算退出。

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

如果您SoftReference要缓存内容,则更有可能发生这种情况-随着堆向最大大小增长,这些引用被清除并可能反复重新生成(取决于您的键循环是否触及)它们,从而导致GC不断发生的一些不良行为但总是恢复足够的内存以继续运行,因为它能够清除一些软引用——即使是 JDK 也会受到这种影响,因为它们在Locale类中使用了这种缓存。

如果您真的想使用 -XX:-UseGCOverheadLimit,您可以禁用此行为。尽管如此,它表明的问题是真实的——你花费不到 2% 的运行时间来做真正的工作。

你在哪里打印出这些内存值?根据您的程序的结构,它可能会生成大量垃圾并在某个内部循环中使用大部分堆,但是在您放置诊断输出的地方,垃圾已被回收。-verbose:gc 可以让您更好地了解实际的 GC 行为。

于 2012-12-29T01:45:01.627 回答