2012-12-29 35 views
4

我不明白如何获得此异常,而JVM使用的总内存(Runtime.totalMemory())大约是一半被分配(Runtime.maxMemory())。任何想法 ?Java:尽管有足够的内存分配可用的“GC开销超限”

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) 
+0

对不起,在之前的回答中,我误导了你,我误读了一些仅与RMI相关的信息。 – pcalcao

回答

1

如前所述pcalcao时,JVM是告诉你,这是花太多时间在垃圾收集上,并且做得不够实际工作,所以它只是要摆脱困境。

这是一种安全阀,可以避免您实际上没有用完内存的情况,但足够接近以至于您确实没有取得任何进展。 this answer有更多的细节,但我会提到一些可能适用于你的情况的东西:

这很可能发生,如果你SoftReference s缓存的东西 - 作为堆向最大尺寸增长,这些引用被清除,并可能反复重新生成(取决于您的密钥循环是否触及)它们,导致GC不断发生的不良行为,但始终会恢复足够的内存以继续执行,因为它可以清除一些软引用 - 甚至JDK也会因为它们在其类Locale中使用这种缓存而受到影响。

如果您确实想使用-XX:-UseGCOverheadLimit,则可以禁用此行为。尽管如此,它指出的问题是真实的 - 您的运行时间花费不到实际工作的2%。

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

+0

没有SoftReference;在这种情况下没有缓存;一个单线程的处理分配...我真的需要RAM:没有什么可以释放的。 –

+1

在一个写得很好的应用程序中,你会得到这个错误是不寻常的,因为你必须用很少的其他处理才能产生大量的对象来触发它,或者可能有奇怪的大小世代。 -verbose:gc将成为你的朋友,也许与jmap或jvisualvm结合使用。 – BeeOnRope

+0

更有可能我们得到错误的日志信息;感谢您的意见我已经接受了回复。你可能想知道Max。内存可能比OS中可用的大(JVM不检查)。 –

相关问题