64位JVM限制为300GB内存?

我试图在集群计算环境(运行CentOS版本6.2 Final的IBM LSF)上运行Java应用程序,它可以为我提供高达1TB的RAM空间 .

我可以创建一个具有高达300GB最大内存(Xmx)的JVM,虽然我需要更多内容(如果需要,我可以提供详细信息) .

但是,使用Xmx选项创建具有超过300GB最大内存的JVM似乎是不可能的 . 更具体地说,我收到了经典的错误消息:

初始化VM时出错 . 无法为对象堆保留足够的空间 .

我的(64位)JVM的详细信息如下:

OpenJDK运行时环境(IcedTea6 1.10.6)(rhel-1.43.1.10.6.el6_2-x86_64)OpenJDK 64位服务器VM(内置20.0-b11,混合模式)

我也尝试过使用Java 7 64位JVM,但我遇到了完全相同的问题 .

此外,我尝试创建一个JVM来运行HelloWorld.jar,但是如果你要求超过-Xmx300G,JVM创建仍然会失败,所以我认为它与特定应用程序没有任何关系 .


有谁知道为什么我不能创建超过300G的最大内存的JVM?

任何人都可以建议解决方案/解决方法吗?

回答(5)

3 years ago

我可以想到几个可能的解释:

  • 系统上的其他应用程序使用的内存太大,目前还没有300Gb可用 .

  • 每进程内存大小可能存在资源限制 . 您可以使用 ulimit 进行检查 . (请注意,根据this bug,如果每个进程资源限制停止JVM分配堆区域,您将收到错误消息 . )

  • 这也可能是“过度提交”问题;例如如果您的应用程序在虚拟环境中运行,并且整个系统无法满足需求,因为来自其他虚拟机的竞争太多 .


建议的其他一些想法(IMO)不太可能:

  • 切换JRE不太可能有任何区别 . 我从未在特定的64位JVM中听到或看到任意内存限制 .

  • 不太可能是由于没有足够的连续内存 . 当然不需要连续的物理内存 . 唯一的可能是交换设备上的连续空间,但我不记得这是典型Linux操作系统的问题 .


任何人都可以建议解决方案/解决方法吗?

  • 检查 ulimit .

  • 编写一个微小的C程序,尝试大量内存并查看在失败之前可以分配多少内存 .

  • 向系统(或管理程序)管理员寻求帮助 .

3 years ago

(已编辑,请参阅有关交换空间的添加部分)

SHMMAX和SHMALL

由于您使用的是CentOS,因此您可能遇到类似 SHMMAXSHMALL 内核设置的问题,如here for configuring the Oracle DB所述 . 在同一链接下是获取和设置正确的 SHMALL 设置的示例计算 .

连续记忆

某些用户已经报告说没有足够的连续内存,其他用户表示这是无关紧要的 .

我不确定CentOS上的JVM是否需要连续的内存块 . According to SAS,碎片化的内存可能会阻止您的JVM以较大的max Xmx 或启动 Xms 内存设置启动,但互联网上的其他声明称它不会有不同的行为,因为每个操作系统的内存管理可能不同(即,Windows通常隐藏单个进程的物理地址) .

查找最大的连续内存块

使用 /proc/meminfo 查找可用的最大连续内存块,请参阅 VmAllocChunk 下的值 . Here's a guide and explanation所有值 . 如果您看到的值小于300GB,请尝试一个低于 VmAllocChunk 值的值 .

但是,通常这个数字高于物理可用内存(因为它是可用的虚拟内存值),它可能会给你误报 . 这是您可以保留的值,但一旦开始使用它,可能需要交换 . 因此,您还应检查 MemFreeInactive 值 . 相反,您还可以查看整个列表,看看哪些值不超过300GB .

您可以检查64位JVM的其他调整选项

我不知道为什么你似乎遇到300GB的内存限制问题 . 有那么一刻,我以为你可能会打到最多的页面 . 默认值为4kB,300GB提供 78,643,200 页面 . 看起来不像一些众所周知的神奇数字 . 例如,如果 2^24 是最大值,则 16,777,216 页面或64GB应该是理论上可分配的最大值 .

但是,假设为了论证你需要更大的页面(事实证明,对于大内存Java应用程序的性能更好),你应该consult this manpage on JBoss,它解释了如何使用 -XX:+UseLargePages 并设置 kernel.shmmax (它再次出现) ), vm.nr_hugepagesvm.huge_tlb_shm_group (不确定后者是否必需) .

强调你的系统

其他人已经提出过这个建议 . 要找出问题在于JVM而不是操作系统,你应该对它进行压力测试 . 您可以使用的一个工具是Stresslinux . In this tutorial,您可以找到一些可以使用的选项 . 您特别感兴趣的是以下命令:

stress --vm 2 --vm-bytes 300G --timeout 30s --verbose

如果该命令失败或锁定了您的系统,您就会知道操作系统正在限制使用该内存量 . 如果成功,我们应该尝试调整JVM,以便它可以使用可用内存 .

编辑Apr6:检查交换空间

具有非常大的内部存储器大小的系统,使用很少或没有交换空间的情况并不少见 . 对于许多应用程序,这可能不是问题,但JVM要求交换可用交换空间大于请求的内存大小 . 根据this bug report,JVM将尝试增加交换空间本身,但是,正如this SO thread suggested中的一些答案,JVM可能并不总是能够这样做 .

因此:使用 cat /proc/swaps # free 检查当前可用的交换空间,如果小于300GB,请按the instructions on this CentOS manpage增加系统的交换空间 .

注1:我们可以从bugreport #4719001中扣除一个连续的可用交换空间块不是必需的 . 但如果你不确定,remove all swap space and recreate it,应删除任何碎片 .

注2:我看过几个帖子,如this one报告 0MB 交换空间,并能够运行JVM . 这可能是由于JVM增加了交换空间本身 . 尝试手动增加交换空间以确定它是否能解决您的问题仍然没有坏处 .

过早的结论

我意识到上述情况不是你问题的开箱即用的答案 . 我希望它能为您提供一些指导,但您可以尝试使JVM正常工作 . 您可能还尝试其他JVM,如果问题证明是您当前使用的JVM的限制,但从我到目前为止所读到的,对64位JVM不应施加限制 .

你在初始化JVM时得到的错误让我相信问题不在于JVM,而在于操作系统无法满足300GB内存的预留 .

我自己的测试表明,JVM可以访问所有虚拟内存,而不关心可用的物理内存量 . 如果虚拟内存低于物理内存,那将是奇怪的,但 VmAllocChunk 设置应该给你一个方向提示(它通常要大得多) .

3 years ago

如果您查看Java HotSpot VM的FAQ section,它提到在64位VM上只有64个地址位可供使用,因此最大Java堆大小取决于物理内存和交换空间的大小在系统上 .

如果你在理论上计算然后你可以有一个 18446744073709551616 MB 的记忆,但它有上述限制 .

您必须使用 -Xmx 命令来定义JVM的最大堆大小,By default,Java在64位JVM上使用64 30%= 83.2MB .

我在我的机器上尝试了以下命令,它看起来工作正常 .

java -Xmx500g com.test.TestClass

我也尝试用TB来定义最大堆,但它不起作用 .

3 years ago

运行ulimit -a作为JVM进程的用户,并验证您的内核不限制您的最大内存大小 . 您可能需要编辑/etc/security/limit.conf

3 years ago

根据this discussion,LSF不会将节点内存池化为单个共享空间 . 你正在使用别的东西 . 阅读那些东西的文档,因为它可能无法完成你要求它做的事情 . 特别是,它可能无法分配跨越所有节点的单个连续内存区域 . 通常这不是必需的,因为应用程序会对malloc进行多次调用 . 但是JVM为自己简化了事情,希望通过有效地调用malloc一次为整个堆分配(或保留)一个连续的区域 . 或者它可能与您用来模拟巨型共享内存机器的其他内容相关 .