Java 32bit Xmx vs java 64bit Xmx

2022-09-03 18:01:28

我对此感到非常困惑。

根据java文档,Xmx是允许的最大堆大小。
Xms 是所需的最小 java 堆大小,在 JVM 启动时分配。

在32位JVM(4GB RAM)上,java -Xmx1536M HelloWorld给出无法分配足够的内存错误。
在64位JVM(4GB Ram)上,java -Xmx20G HelloWorld工作得很好。但我甚至没有分配那么多的虚拟或物理内存。

因此,由此,我得出结论,Java 32位在JVM启动时分配了1536M,但Java 64位不是。

为什么?一个简单的Hello World应该不需要1536M来运行。我只是指定1536M是最大值,而不是需要它。

有人解释吗?


答案 1

分配内存和分配地址空间之间是有区别的。Oracle JVM 在启动时分配地址空间,以确保堆是连续的。这允许对堆使用某些优化。

如果分配失败,则 Java 将不会启动...正如你所看到的。它不一定使用那么多内存,但它正在预先分配所需的地址空间。既然你通过了,它说好,我需要分配,以防你需要它...并且由于它必须是连续的,因此它会预先执行此操作,因此可以保证它(或尝试失败)。-Xmx1536m

此行为在 32 位和 64 位 JVM 上是相同的。您看到的是32位进程的每个进程2GB的地址空间限制(至少在Windows上这是限制 - 在其他平台上可能略大),导致此分配在32位上失败,其中64位没有问题,因为它具有更大的地址空间。但是,你说,1536m不到2GB,我应该很好,对吧?不完全是 - 堆不是地址空间中分配的唯一东西,DLL和其他东西也分配在地址空间中...因此,不幸的是,在32位上从2GB最大值中获得连续的1536m块是非常不可能的。我见过低于1000m的值在32位进程上失败,碎片特别严重,通常1200-1300m是您可以在32位上指定的最大堆。

在现代操作系统上,ASLR(地址空间布局随机化)使 32 位进程地址空间的碎片化更加严重。出于安全原因,它有意将 DLL 加载到随机地址中...使您更不可能在 32 位中获得一个大的、连续的堆。

在 64 位中,地址空间非常大,以至于碎片不再是问题,并且可以毫无问题地分配巨大的堆。但是,即使您在32位上有4GB的RAM,每个进程2GB的地址空间限制(至少在Windows上)通常意味着最大堆通常只有1300m左右。


答案 2

实际上,应用程序在启动时没有分配Xmx内存。

-Xms 参数配置启动内存。(启动 JVM 时的 Xms 和 Xmx 参数是什么?)

64位环境允许更大的内存分配,然后是32位。但是,事实上,它使用的是HD空间,而不是内存RAM。

有关详细信息,请参阅此其他帖子。

估计 64 位 Java 中的最大安全 JVM 堆大小