Java堆 - 比它需要的更大

bif*_*fta 5 java memory

我的数学表明以下Java程序需要大约8GB(2147483645*4字节)的RAM:

package foo;

public class Foo {
    public static void main(String[] args) throws Exception {
        int[] arr = new int[Integer.MAX_VALUE-2];
        Thread.sleep(500000L);
    }
}
Run Code Online (Sandbox Code Playgroud)

这可以通过在运行时观察程序来备份: jvisualvm记忆图片

但除非您将最大堆设置为大约12.5GB,否则程序无法启动:

$ java -Xmx12000m -cp ./ foo.Foo
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at foo.Foo.main(Foo.java:5)
$ java -Xmx12500m -cp ./ foo.Foo
//this works
Run Code Online (Sandbox Code Playgroud)

可以理解需要一些摆动但我们为什么需要这么多?

Art*_*dim 5

它是因为MinHeapFreeRatio的默认值(即40%).如果你想"少需要"那么你必须指定它:例如5% -XX:MinHeapFreeRatio=5

此外,您需要更改分配给年轻代的内存,因为它在内存分配中起着重要作用:

在总可用内存之后,影响垃圾收集性能的第二个最有影响的因素是专用于年轻代的堆的比例.

试试这个:

java -Xmx9g -XX:MinHeapFreeRatio=1 -XX:MaxNewSize=256m -cp ./ foo.Foo
Run Code Online (Sandbox Code Playgroud)

https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/sizing.html