前言
我们都知道JVM有一个堆内存的概念,可以通过JVM参数-Xmx(最大堆大小),-Xms(初始堆大小)来进行设置。
在不通过命令行参数指定初始堆大小和最大堆大小时,默认情况下,初始堆大小和最大堆大小到底是多少呢?
堆内存默认大小
官方默认值规则
直接查看JDK8官方文档
翻译后规则如下:
-
-
默认最大堆大小(
-Xmx
):如果物理内存小于 192MB,则最大堆大小占物理内存的一半,否则占物理内存的四分之一。在32位JVM上,如果有4 GB或更多的物理内存,则默认的最大堆大小可达1 GB。在64位JVM上,如果有128 GB或更多的物理内存,则默认的最大堆大小最多可达32 GB。
-
-
- 默认初始堆大小(
-Xms
): 在JVM初始化期间分配了一个较小的值,称为初始堆大小。此数量为物理内存的1/64,最大为1 GB,至少为8 MB。
- 默认初始堆大小(
-
- 分配给年轻代的最大空间量是堆总大小的三分之一,即年轻代和老年代默认的比例是1:2
-
- 可以使用-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
这种方式会跟着主机环境动态变化,但是可以看到这个值,基本与前面两种方式接近。