64 位 JVM 限制为 300GB 内存?

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

我可以创建一个最大内存高达300GB的JVM(Xmx),尽管我需要更多(如果需要,我可以提供详细信息)。

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

VM 初始化期间发生错误。

无法为对象堆保留足够的空间。

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

OpenJDK Runtime Environment (IcedTea6 1.10.6) (rhel-1.43.1.10.6.el6_2-x86_64)

OpenJDK 64 位服务器虚拟机(内部版本 20.0-b11,混合模式)

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

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


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

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


答案 1

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

  • 系统上的其他应用程序正在使用如此多的内存,以至于现在没有300Gb可用

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

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


建议的其他几个想法(IMO)不太可能:

  • 切换 JRE 不太可能产生任何影响。我从未听说过或见过特定64位JVM中的任意内存限制。

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


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

  • 检查 .ulimit

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

  • 向系统(或虚拟机管理程序)管理员寻求帮助。


答案 2

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

SHMMAX 和 SHMALL

由于您使用的是 CentOS,因此您可能会遇到有关和内核设置的类似问题,如此处所述,用于配置 Oracle DB。在同一链接下是用于获取和设置正确设置的示例计算。SHMMAXSHMALLSHMALL

连续记忆

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

我不確定 CentOS 上的 JVM 是否需要連續的記憶體區。根据SAS的说法,碎片内存可能会阻止您的JVM以较大的max或启动内存设置启动,但互联网上的其他声明说这无关紧要。我试图在我的48GB Windows工作站上证明或取消证明这一说法,但设法以40GB的初始和最大设置启动了JVM。我很确定没有这种大小的连续块可用,但是不同操作系统上的JVM可能行为不同,因为每个操作系统的内存管理可能不同(即,Windows通常隐藏各个进程的物理地址)。XmxXms

查找最大的连续内存块

用于查找最大的可用连续内存块,请参阅下的值。以下是所有值的指南和说明。如果看到的值小于 300GB,请尝试正好位于 的值。/proc/meminfoVmAllocChunkVmAllocChunk

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

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

我不确定为什么您似乎在300GB处遇到内存限制问题。有那么一刻,我以为你可能已经达到了最多页面。默认值为 4kB,300GB 提供页面。看起来不像一些众所周知的神奇数字。例如,如果是最大值,则页数或 64GB 应该是理论上可分配的最大值。78,643,2002^2416,777,216

但是,假设为了论证您需要更大的页面(事实证明,这对于大内存Java应用程序的性能更好),您应该查阅JBoss上的这个手册页,其中解释了如何使用和设置(再次出现),以及(不确定后者是否是必需的)。-XX:+UseLargePageskernel.shmmaxvm.nr_hugepagesvm.huge_tlb_shm_group

给系统带来压力

其他人也已经提出了这一点。要找出问题出在JVM而不是操作系统上,您应该对其进行压力测试。你可以使用的一个工具是 Stresslinux在本教程中,您将找到一些可以使用的选项。您特别感兴趣的是以下命令:

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

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

编辑4月6日:检查交换空间

具有非常大的内部内存大小的系统很少使用交换空间或不使用交换空间的情况并不少见。对于许多应用程序来说,这可能不是问题,但 JVM 要求交换可用交换空间大于请求的内存大小。根据此错误报告,JVM 将尝试增加交换空间本身,但是,正如此 SO 线程中的一些答案所建议的那样,JVM 可能并不总是能够这样做。

因此:检查当前可用的交换空间,如果它小于300GB,请按照此CentOS手册页上的说明增加系统的交换空间。cat /proc/swaps # free

注意1:我们可以从bugreport #4719001中推断出,可用交换空间的连续块不是必需的。但是,如果您不确定,请删除所有交换空间并重新创建它,这应该会删除任何碎片。

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

过早结论

我意识到以上都不是你问题的开箱即用的答案。我希望它能给你一些指导,你可以尝试让你的JVM工作。如果问题证明是您当前使用的JVM的限制,您也可以尝试其他JVM,但是从我到目前为止所读到的内容来看,不应该对64位JVM施加任何限制。

您在初始化JVM时遇到错误使我相信问题不在于JVM,而在于操作系统无法遵守300GB内存的保留。

我自己的测试表明,JVM可以访问所有虚拟内存,并且不关心可用的物理内存量。如果虚拟内存低于物理内存,那将是奇怪的,但该设置应该在该方向上为您提供提示(通常要大得多)。VmAllocChunk