全盘掌控堆空间的大小

先来回顾一下默认堆的大小

操作系统及JVM类型 Xms Xmx
Linux 32位 Client 16MB 256MB
Linux 32位 Server 64MB 取1GB和物理内存大小1/4二者中的最小值
Linux 64位 Server 取512MB和物理内存大小1/64二者中的最小值 取32GB和物理内存大小1/4二者中的最小值
MacOS 64位 Server 64MB 取1GB和物理内存大小1/4二者中的最小值
Window 32位 Client 16MB 256MB
Window 64位 Server 64MB 取1GB和物理内存大小1/4二者中的最小值

堆的默认大小依据机器的内存配置确定,不过也可以通过参数-XX:MaxRAM=N-XX:MaxRAMFraction=N设置。
通常情况下,这个值是由JVM检测机器的物理内存计算得出。

MaxRam的最大值

操作系统及JVM类型 MaxRam
32 位 client 1 GB
32 位 server 4 GB
64 位 server 128 GB

默认最大堆的计算实际采用下面的公式:

Default Xmx = MaxRAM / MaxRAMFraction

而MaxRAMFraction的默认值为4,即堆的最大容量是MaxRAM值的四分之一。

JVM还提供了另一个参数调整最大堆的默认值,这个参数是-XX:ErgoHeapSizeLimit=N
该参数默认值为0(表示忽略该标志),如果设置的限制值比MaxRAM/MaxRAMFraction还小,就使用该参数指定的值。

另一方面,如果机器配置的物理内存非常少,JVM还要确保预留足够的内存给操作系统使用。
这个值的计算是基于-XX:MinRAMFraction=N参数,默认值为2。

if ((96 MB * MinRAMFraction) > Physical Memory) {
    Default Xmx = Physical Memory / MinRAMFraction;
}

这就是为什么堆的默认大小在不同的机器上会有不同的原因:
如果机器的物理内存比MaxRAM的值小,默认堆的大小就是物理内存的1/4。即使机器配置了数百GB的内存,JVM能使用的最大堆容量也不会超过默认值32GB,即128GB的1/4。