Java 32bit Xmx vs java 64bit Xmx



我真的对此感到困惑

Xmx根据java文档,是允许的最大堆大小
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是最大值,而不是说它是必需的

有人解释吗?

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

如果分配失败,那么Java将不会启动。。。正如你所看到的。它不一定要使用那么多内存,但它会预先分配所需的地址空间。由于你正在传递-Xmx1536m,它说好的,我需要分配它以备你需要……由于它必须是连续的,它会提前进行,这样它就可以保证它(或尝试失败)。

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

在现代操作系统上,ASLR(地址空间布局随机化)使32位进程地址空间的碎片化变得更糟。出于安全考虑,它有意将DLL加载到随机地址中。。。这样就不太可能在32位中得到一个大的、连续的堆。

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

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

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

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

有关更多信息,请参阅其他帖子。

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

在Windows下,内存分配操作与本机WinAPI低级函数(如VirtualAlloc)不同。

"保留"是指在进程地址空间内分配一个连续区域,而不实际使该虚拟内存区域可用。分配的区域不由实际的物理RAM或交换空间支持,并且不消耗任何可用内存。任何应用程序都可以保留仅受处理器的内存寻址能力(位)限制的任何数量的地址空间。

"提交"意味着用实际内存(RAM或交换空间)支持一些以前"保留"的内存,使其实际上可由进程读取/写入。此内存取自可用的操作系统虚拟内存池(RAM和交换)。

"提交"内存(从池中获取空白页)的另一种方法是将文件"映射"到以前的"保留"内存中。这不会消耗交换池中的内存,而是以类似于进程地址空间特定区域的专用交换空间的方式使用映射文件。

本机Windows应用程序(如JVM本身)为将来需要的所有堆保留内存,但仅在需要时提交。像malloc()风格的函数或"new"操作符这样的高级内存操作确实可以根据需要进行"提交",甚至可以在内存由大块提前提交的情况下进行自己的堆管理逻辑用户模式,因为这是一个CPU密集型内核调用,以页面(4k)粒度工作。

在进程启动期间,JVM"保留"-Xmx内存,但"提交"的内存量仅为-Xms。剩余的保留内存将随着堆的增长而按需提交。因此,堆可以增长到可用内存或-Xmx参数,以较小者为准。

最新更新