如果不通过JVM参数指定堆大小,你知道默认值是多少吗?

232 阅读3分钟

前言

我们都知道JVM有一个堆内存的概念,可以通过JVM参数-Xmx(最大堆大小),-Xms(初始堆大小)来进行设置。

在不通过命令行参数指定初始堆大小和最大堆大小时,默认情况下,初始堆大小和最大堆大小到底是多少呢?

image.png

堆内存默认大小

官方默认值规则

直接查看JDK8官方文档

image.png

翻译后规则如下:

    1. 默认最大堆大小(-Xmx):如果物理内存小于 192MB,则最大堆大小占物理内存的一半,否则占物理内存的四分之一。

      在32位JVM上,如果有4 GB或更多的物理内存,则默认的最大堆大小可达1 GB。在64位JVM上,如果有128 GB或更多的物理内存,则默认的最大堆大小最多可达32 GB。

    1. 默认初始堆大小(-Xms): 在JVM初始化期间分配了一个较小的值,称为初始堆大小。此数量为物理内存的1/64,最大为1 GB,至少为8 MB。
    1. 分配给年轻代的最大空间量是堆总大小的三分之一,即年轻代和老年代默认的比例是1:2
    1. 可以使用-Xms(初始堆大小)和-Xmx(最大堆大小)来指定初始堆大小和最大堆大小。如果你知道你的应用程序有多少堆需要工作做好,你可以设置-Xms和-Xmx相同的值。否则,JVM将使用初始堆大小开始,然后将增大Java堆,直到找到堆使用率和性能之间的平衡为止。

我本机是Mac 64位操作系统,物理内存为8G。按如上规则,那么可以计算出:

  • 默认初始堆大小=8G*1/64=128MB
  • 默认最大堆大小=8G*1/4=2G

另外,还可以通过如下两种方式查看,同时对上述的结果进行证实。

查看堆默认大小的两种方式

方式一:通过JVM -XX:+PrintFlagsFinal 命令

执行及结果:
(base) landeMacBook-Pro:~ lan$ java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize'

    uintx ErgoHeapSizeLimit                         = 0                                   {product}

    uintx HeapSizePerGCThread                       = 87241520                            {product}

    uintx InitialHeapSize                          := 134217728                           {product} 

    uintx LargePageHeapSizeThreshold                = 134217728                           {product}

    uintx MaxHeapSize                              := 2147483648                          {product}

java version "1.8.0_191"

Java(TM) SE Runtime Environment (build 1.8.0_191-b12)

Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

初始堆大小:参数InitialHeapSize := 134217728字节,134217728/1024/1024=128MB
最大堆大小:参数MaxHeapSize := 2147483648字节,2147483648/1024/1024=2048MB=2G

方式二:通过Java代码

public class  InitialAndMaximumHeapSizeTest {

    public static void main(String[] args) {
        // 获取堆内存信息
        // 最大堆大小
        long maxHeapSize = Runtime.getRuntime().maxMemory();
        // 初始堆大小
        long totalHeapSize = Runtime.getRuntime().totalMemory();

        System.out.println("Max Heap Size: " + maxHeapSize / (1024 * 1024) + " MB");
        System.out.println("Total Heap Size: " + totalHeapSize / (1024 * 1024) + " MB");
   }     
}
执行结果:
Max Heap Size: 1820 MB
Total Heap Size: 123 MB

这种方式会跟着主机环境动态变化,但是可以看到这个值,基本与前面两种方式接近。