Java堆大小未完全使用

我正在使用Visual VM监视我正在运行的java应用程序: http : //visualvm.java.net/

我用-Xmx128m强调内存使用量。

运行时我看到堆大小增加到128m(正如预期的那样)但是在遇到java堆空间错误之前,使用的堆收敛到大约105m。

在此处输入图像描述

为什么这些剩下20米,没用过?

堆在Young-Generation(Eden-Space和两个相同大小的Survivor-Spaces,通常称为From和To),Old Generation(Tenured)和Permanent Space中分开。

Xmx/Xms选项设置整个堆大小。 所以一个区域(默认大小)实际上是永久空间 – 也许,我们不知道你的压力测试的细节,实际上没有任何物体从伊甸园转移到终身或永久,所以这些区域仍然是空的,而伊甸园用完了空间。

您需要了解垃圾收集器人机工程学的核心事实:

垃圾收集的昂贵部分是查找和处理非垃圾的对象。

这意味着:随着堆接近其最大容量,GC将花费越来越多的时间在回收空间中获得越来越少的回报。 如果GC试图使用内存的每个最后一个字节,那么最终的结果就是你的JVM会花费越来越多的时间进行垃圾收集,直到……最终……几乎没有任何有用的工作正在完成。

为了避免这种病态,JVM监视GC用于和执行有用工作的时间比。 当比率超过可配置的阈值时,GC会引发OutOfMemoryError …即使(技术上)有可用的可用内存。 这可能就是你所看到的,尽管其他解释同样合理。

您可以通过JVM选项更改GC阈值,生成大小等,但最好不要这样做。 更好的想法是弄清楚为什么你的应用程序的内存使用量不断上升。 最有可能是内存泄漏…即代码中的错误…导致此问题。 花费你的努力来发现和修复这些错误,而不是担心为什么你没有使用所有的内存。

(事实上​​,你正在使用它……但不是所有的时间。)

Java将其内存分为几代。 如果终生代填充,则可能会出现堆空间错误。 通常,它们会动态resize,但如果您设置了固定大小,则不会。