我不明白如何获得此异常,而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)
答案 0 :(得分:1)
正如pcalcao所提到的,JVM告诉你它在垃圾收集上花费了太多时间,并且没有做足够的实际工作,所以它只会挽救。
这是一种安全阀,可以避免您实际上没有内存耗尽,但足够接近以至于您确实没有取得任何进展。我不会强调这一点 - this answer有更多细节,但我会提到一些可能适用于你案件的事情:
如果您SoftReference
要缓存内容,则更有可能发生这种情况 - 当堆增长到最大大小时,这些引用会被清除并可能重复重新生成(取决于您的密钥循环是否接触)它们,结果在GC不断发生的一些不良行为中,总是恢复足够的内存以继续运行,因为它能够清除一些软引用 - 甚至JDK也会因为它们在Locale
类中使用这种缓存而受此影响。
如果您真的想使用-XX,可以禁用此行为:-UseGCOverheadLimit。尽管如此,它表明的问题仍然存在 - 您花费的时间不到运行时间的2%。
你在哪里打印出那些记忆值?根据程序的结构,它可能会产生大量垃圾并在一些内部循环中使用大部分堆,但是在放置诊断输出的地方,垃圾被回收。 -verbose:gc可以更好地描述实际的GC行为。