Java 32 位 Xmx 与 Java 64 位 Xmx
Posted
技术标签:
【中文标题】Java 32 位 Xmx 与 Java 64 位 Xmx【英文标题】:Java 32bit Xmx vs java 64bit Xmx 【发布时间】:2014-01-21 15:52:10 【问题描述】:我真的很困惑。 根据 java 文档,Xmx 是允许的最大堆大小。 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 是最大值,而不是需要它。 解释一下吗?
【问题讨论】:
【参考方案1】:分配内存和分配地址空间是有区别的。 Oracle JVM 在启动时分配 地址空间 以确保堆是连续的。这允许对堆使用某些优化。
如果分配失败,那么 Java 将无法启动……正如您所见。它不一定使用那么多内存,但它会预先分配所需的地址空间。既然你通过-Xmx1536m
,它说好的,我需要分配它以防你需要它......并且由于它必须是连续的,所以它可以预先完成它,所以它可以保证它(或尝试失败)。
这种行为在 32 位和 64 位 JVM 上是相同的。您所看到的是 32 位进程的每个进程 2GB 的地址空间限制(至少,在 Windows 上这是限制 - 在其他平台上可能稍大)导致此分配在 32 位上失败,其中 64 -bit 没有问题,因为它具有更大的地址空间。但是,你说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 参数配置启动内存。 (What are the Xms and Xmx parameters when starting JVMs?)
64 位环境允许比 32 位更大的内存分配。但实际上,它使用的是 HD 空间,而不是内存。
查看其他帖子了解更多信息。
Estimating maximum safe JVM heap size in 64-bit Java
【讨论】:
+1 对于 32 位 Linux,您可以使用java -Xmx3g
,它是 Windows 32 位,其连续地址空间有限。【参考方案3】:
在 Windows 下,内存分配操作与 VirtualAlloc 等原生 WinAPI 低级函数存在差异。
“保留”是指在进程地址空间内分配一个连续区域,但实际上并不使该虚拟内存区域可用。分配的区域不受实际物理 RAM 或交换空间的支持,并且不消耗任何可用内存。任何应用程序都可以保留任何数量的地址空间,仅受处理器的内存寻址能力(位)限制。
“提交”是指用实际内存(RAM 或交换空间)支持一些以前“保留”的内存,使其实际可被进程读取/写入。此内存取自可用的操作系统虚拟内存池(RAM 和交换)。
“提交”内存(从池中获取空白页)的替代方法是将文件“映射”到先前“保留”的内存中。这不会消耗交换池中的内存,而是以类似于进程地址空间的特定区域的专用交换空间的方式使用映射文件。
本机 Windows 应用程序(如 JVM 本身)为将来需要的所有堆保留内存,但仅在需要时提交。 高级内存操作,如 malloc() 样式函数或“新”操作符,确实根据需要执行“提交”,甚至执行自己的堆管理逻辑用户模式,内存由大块提前提交,因为它是 CPU 密集型内核调用并以页面 (4k) 粒度工作。
在进程启动期间,JVM“保留”-Xmx 内存,但“提交”仅 -Xms 量。随着堆的增长,剩余的保留内存将按需提交。因此堆可以增长到可用内存或 -Xmx 参数,以较小者为准。
【讨论】:
以上是关于Java 32 位 Xmx 与 Java 64 位 Xmx的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Open Office(32 位)与 64 位 Java 运行时环境集成?
java.lang.IllegalStateException 执行 Ghost4J(Linux 32 与 64 位)