繁体   English   中英

Java 32bit Xmx vs java 64bit Xmx

[英]Java 32bit Xmx vs java 64bit Xmx

我真的很困惑。

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

在32位JVM(4GB内存)上,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位和64位JVM上都是相同的。 您所看到的是32位进程的2GB每进程地址空间限制(至少,在Windows上这是限制 - 在其他平台上可能略大)导致此分配在32位上失败,其中64 -bit没有问题,因为它有更大的地址空间。 但是,你说,1536米不到2GB,我应该好,对吧? 不完全 - 堆不是在地址空间中分配的唯一东西,DLL和其他东西也在地址空间中分配...所以不幸的是,在32位上从2GB最大值获得连续的1536m块是不太可能的。 我已经看到低于1000m的值在32位进程上失败,碎片特别糟糕,通常1200-1300m是您可以在32位上指定的最大堆。

在现代操作系统中, ASLR (地址空间布局随机化)使32位进程地址空间的碎片更加糟糕。 出于安全原因,它故意将DLL加载到随机地址中...使得它甚至不太可能在32位中获得大的连续堆。

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

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

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

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

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

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

在Windows下,内存分配操作与VirtualAlloc等本机WinAPI低级功能存在差异。

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

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

“提交”存储器(从池中取空白页)的替代方法是将文件“映射”到先前“保留”的存储器中。 这不会占用交换池中的内存,但会以类似于进程地址空间的特定区域的专用交换空间的方式使用映射文件。

本机Windows应用程序(如JVM本身)为将来需要的所有堆保留内存,但仅在需要时提交。 像malloc()样式函数或“新”运算符这样的高级内存操作确实可以根据需要“提交”,甚至可以执行自己的堆管理逻辑用户模式,其中内存由大块提交,因为它是CPU密集型内核在页面(4k)粒度调用和工作。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM