Java 拒绝启动 - 无法为对象堆保留足够的空间
Posted
技术标签:
【中文标题】Java 拒绝启动 - 无法为对象堆保留足够的空间【英文标题】:Java Refuses to Start - Could not reserve enough space for object heap 【发布时间】:2010-11-06 16:56:50 【问题描述】:背景
我们有大约 20 个 linux 刀片库。有些运行 Suse,有些运行 Redhat。 ALL 共享 NAS 空间,包含以下 3 个文件夹:
/NAS/app/java - 指向 Java JDK 安装的符号链接。当前版本 1.5.0_10 /NAS/app/lib - 指向我们应用程序版本的符号链接。 /NAS/data - 写入输出的目录我们所有的机器都有 2 个处理器(超线程),具有 4gb 的物理内存和 4gb 的交换空间。我们将每台机器在给定时间可以处理的“作业”数量限制为 6 个(这个数字可能需要更改,但这不属于当前问题,因此请暂时忽略它)。
我们的一些作业将最大堆大小设置为 512mb,而另一些作业将最大堆大小保留为 2048mb。同样,我们意识到如果在同一台机器上启动 6 个作业并将堆大小设置为 2048,我们可能会超出可用内存,但据我们所知,这还没有发生。
问题
有时,Job 会立即失败并显示以下消息:
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
我们过去常常将此归咎于同一台机器上同时运行的作业太多。该问题很少发生(可能每月一次),我们只需重新启动它,一切都会好起来的。
这个问题最近变得更糟了。我们所有请求最大堆大小为 2048m 的作业几乎每次都会立即失败,并且需要重新启动几次才能完成。
我们已经使用了个别机器并尝试手动执行它们,结果相同。
调试
事实证明,问题只存在于我们的 SuSE 盒子。它发生得更频繁的原因是因为我们一直在添加更多的机器,而新的机器是 SuSE。
SuSE 框中的“cat /proc/version”给我们:
Linux version 2.6.5-7.244-bigsmp (geeko@buildhost) (gcc version 3.3.3 (SuSE Linux)) #1 SMP Mon Dec 12 18:32:25 UTC 2005
RedHat 盒子上的“cat /proc/version”给我们:
Linux version 2.4.21-32.0.1.ELsmp (bhcompile@bugs.build.redhat.com) (gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-52)) #1 SMP Tue May 17 17:52:23 EDT 2005
'uname -a' 在两种类型的机器上为我们提供以下信息:
UTC 2005 i686 i686 i386 GNU/Linux
机器上没有正在运行的作业,也没有其他进程占用太多内存。当前运行的所有进程可能总共使用 100mb。
'top' 当前显示如下:
Mem: 4146528k total, 3536360k used, 610168k free, 132136k buffers
Swap: 4194288k total, 0k used, 4194288k free, 3283908k cached
'vmstat' 当前显示如下:
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 0 610292 132136 3283908 0 0 0 2 26 15 0 0 100 0
如果我们使用以下命令行启动作业(最大堆为 1850mb),它会正常启动:
java/bin/java -Xmx1850M -cp helloworld.jar HelloWorld
Hello World
如果我们将最大堆大小增加到 1875mb,它会失败:
java/bin/java -Xmx1875M -cp helloworld.jar HelloWorld
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
很明显,当前使用的内存是用于缓冲/缓存的,这就是为什么很少显示为“空闲”的原因。不清楚的是为什么会有一个神奇的 1850mb 行,任何更高的值都意味着 Java 无法启动。
任何解释将不胜感激。
【问题讨论】:
见***.com/questions/171205/…。 为什么有 32b 刀片? :P 嗨,Randyaa,您最终找出造成这种情况的原因了吗?当我尝试启动 WebLogic 服务器时,我遇到了同样的错误......谢谢 很遗憾,没有,我们实施了一些技术来减少内存使用量,并且能够将最大使用量降低到 1gig 左右。对不起:( +1 细节丰富。 【参考方案1】:您使用的是 32 位操作系统,因此您会看到总大小的限制。其他答案已经更详细地介绍了这一点,因此我将避免重复他们的信息。
我最近在我们的服务器上注意到的一个行为是,使用 -Xmx
指定最大堆大小而不使用 -Xms
指定最小堆大小会导致 Java 的服务器 VM 立即尝试分配所需的所有内存最大堆大小。当然,如果应用程序达到该堆大小,这就是您需要的内存量。但很有可能,您的应用一开始会使用相对较小的堆,可能在以后需要更大的堆。此外,指定最小堆大小将使您的应用从较小的堆开始,然后逐渐增大该堆。
所有这些都不会帮助您增加最大堆大小,但我认为它可能会有所帮助,所以...
【讨论】:
我已经提到过,我认为这与我们的 32 位操作系统无关。 SuSE 和 RedHat 机器都是 32 位的,它们都没有问题。至于您设置最小值的建议,我试过了,但对我没有任何帮助:(。【参考方案2】:正如其他回复中所建议的,问题是由虚拟地址空间耗尽引起的。一个 32 位的 linux 用户空间程序通常限制为 3GB 的 AS;剩余的 1GB 由内核使用(理由:由于顶部 1GB 是内核固定映射,因此在提供系统调用时无需触及页表)。
但是,RHEL 内核实现了所谓的 4GB/4GB 拆分,其中完整的 4GB AS 可用于用户空间进程,但运行时开销很小(内核位于单独的 4GB 虚拟 AS 中)
【讨论】:
【参考方案3】:运行 32 位操作系统是错误的;您一定要尽早升级。
我不知道 Java 是否要求其堆位于单个连续块中,但如果需要,在 32 位机器上要求 1.8G 的堆听起来是一项艰巨的任务。您假设在 JVM 启动时有一块地址空间,几乎一半是空闲的。
根据当时加载的其他库,可能没有。库可以在他们喜欢的任何地方分配内存,因此它可以充分分割您的地址空间,以至于 1.8G 无法在一个块中使用。
无论如何,Linux 32 位上最多只有大约 3G 的地址空间可用。库和 JVM 本身使用一些来开始。
【讨论】:
如果可以的话我会换的。这不取决于我。我需要解决手头的问题,这就是 Redhat 机器允许我们使用 2500+ 以及 SuSE 机器将我们限制为 1850 的原因。【参考方案4】:对于 32 位服务器,似乎存在无法克服的 JVM 限制(除非您找到不施加 2GB 或更少限制的特殊 32 位 JVM)。
服务器端的这个线程有更多细节,包括几个人在 32 位架构上测试了各种 JVM。 IBM 的 JVM 似乎允许多出 100 MB,但这并不能真正满足您的需求。
http://www.theserverside.com/discussions/thread.tss?thread_id=26347
“真正的”解决方案是使用带有 64 位 JVM 的 64 位服务器来获得每个进程大于 2GB 的堆。但是,重要的是还要考虑使用 64 位 JVM 增加地址大小(不仅仅是可寻址空间)的影响。使用少于 4GB 内存的处理可能会对性能和内存产生影响。
深思:这些工作真的需要 2GB 内存吗?有什么办法可以将作业修改为在 1.8GB 内运行,这样这个限制就没有问题了?
【讨论】:
我真的不认为这是一个 32 位的问题。两台机器都运行 32 位操作系统,它们各自有不同的限制。 RedHat 盒子限制在 2500+MB 左右,SuSE 盒子在 1850Mb 左右。 至于更改系统或“真的”需要 2GB... 我们计划进行一些更改以减少内存印记,但是;在这一点上是的,它确实需要。【参考方案5】:ulimit 最大内存大小和虚拟内存设置为无限制?
【讨论】:
ulimit 在两者上都是无限的。我在哪里检查虚拟内存限制? 将 ulimit 与 -a 开关一起使用。ulimit -a
【参考方案6】:
我写了两个应用程序,一个中等大小,另一个相当小。我会开火 中型(在 linux,centos 上),没有任何 args,(java 服务器),它会 运行得很好。但是当我用“java客户端”启动较小的应用程序时,它会告诉 我它无法保留足够的空间,也不会运行。我进行了实验,并使用了 10m 的 -Xms 和 -Xmx,它们都可以毫无怨言地运行......去看看!
【讨论】:
【参考方案7】:这可能偏离了正轨,但有两件事情浮现在脑海中。以下两项均假设您运行的是 32 位版本的 Linux。
Linux 上有一个进程大小限制,似乎记得在 CentOS 上大约是 2.5gb,并且在内核中进行了配置(即重新完成更改)。一旦您将所有 JVM 代码 + Permgen 空间和所有其余 JVM 库相加,您的进程可能会遇到这种情况。
第二件事是我遇到的事情,您可能会用完地址空间,我知道这听起来很奇怪。使用 1.5Gb 堆运行 Glassfish 时出现问题,当它尝试编译一个 JSP 我的分叉 javac 时它会失败,因为即使盒子中有 12GB 内存,操作系统也无法为新创建的进程分配足够的地址空间。这里可能会发生类似的事情。
恐怕只有以上两个的解决办法,哪里升级到64位内核。
希望这有一些用处。
【讨论】:
正如我已经提到的,如果 SuSE 盒子和 RedHat 盒子都有这个问题,我会同意你的看法。它们都是 32 位操作系统,它们有不同的限制。 Redhat 似乎在 2500+ MB 左右,而 SuSE 盒子似乎在 1850 MB 左右。 不同的发行版可能有不同的进程大小限制默认值。它们也有不同的内核版本。【参考方案8】:您需要考虑升级您的操作系统和 Java。 Java 5.0 已停产,但如果您无法更新到 Java 6,您可以使用最新的补丁级别 22!
32 位 Windows 限制为 ~ 1.3 GB,因此您可以将最大值设置为 1.8。注意:这是连续内存的问题,当您的系统运行时,它的内存空间可能会变得碎片化,所以我不会惊讶您有这个问题。
64 位操作系统没有这个问题,因为它有更多的虚拟空间,您甚至不必升级到 64 位版本的 java 即可利用这一点。
顺便说一句,根据我的经验,32 位 Java 5.0 可以比 64 位 Java 5.0 更快。直到多年后,Java 6 update 10 才更快地用于 64 位。
【讨论】:
【参考方案9】:我把一台机器的内存从2GB升级到4GB,马上就开始报错:
$ java -version
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
问题在于 ulimit,我将可寻址空间设置为 1GB。 将其增加到 2GB 解决了这个问题。
-Xms 和 -Xmx 没有效果。
看起来 java 试图获取与可用内存成比例的内存,如果不能,则失败。
【讨论】:
【参考方案10】:要执行的步骤 .... 解决 初始化虚拟机时出错 无法为对象堆保留足够的空间 无法创建 Java 虚拟机。
第 1 步:减少之前使用的内存。 java -Xms128m -Xmx512m -cp simple.jar
第 2 步:从主板上取下 RAM 一段时间,然后将其插入并重新启动 * 可能会释放阻塞堆区域内存.. java -Xms512m -Xmx1024m -cp simple.jar
希望它现在运行良好... :-)
【讨论】:
【参考方案11】:我最近遇到了这个问题。我有 3 个以 1024m 或 1280m 堆大小开头的 java 应用程序。 Java 正在查看 swap 中的可用空间,如果没有足够的可用内存,则 jvm 退出。
为了解决这个问题,我不得不结束几个分配了大量虚拟内存的程序。
我在带有 64 位 jvm 的 x86-64 linux 上运行。
【讨论】:
【参考方案12】:使用的 JVM 是什么? 我知道 BEA JRockit 的最大堆大小不超过 1850mB。它不会失败,但会警告用户它不会使用超过 1850mB。
我不知道为什么会有这样的限制,但我知道它存在于 BEA JRockit。
最好的问候。
【讨论】:
我们只是使用 Sun 的 JVM。 java version "1.5.0_10" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_10-b03) Java HotSpot(TM) Server VM (build 1.5.0_10-b03, mixed mode) 我刚刚在 Windows XP 上使用 Sun 客户端 VM 进行了测试。以上 -Xmx1640M 我得到了和你一样的错误: 初始化 VM 时发生错误 无法为对象堆保留足够的空间 无法创建 Java 虚拟机。我测试的程序是HelloWorld。该限制由 JVM 固定。 Oracle JRockit 与 Sun 和 IBM 的 JVM:s 不同,它可以使用非连续堆。这意味着您可以在 Windows 上获得近 3 GB,但不确定在 Linux 上可以获得多少。有关更多信息,请参阅此博客; blogs.oracle.com/jrockit/2008/09/…【参考方案13】:鉴于其他建议均无效(包括我自己建议的许多事情),为了帮助进一步排除故障,您能否尝试运行:
sysctl -a
在 SuSE 和 RedHat 机器上查看是否有任何差异?我猜这两个发行版的默认配置是不同的。
【讨论】:
/sbin/sysctl 在您的路径中吗?实际上,只需尝试运行 /sbin/sysctl -a。【参考方案14】:我正在使用 SOA 环境,将 setSOADomainENV.cmd
中的 Xmx 从 1024 减少到 768 解决了这个问题。
REM set DEFAULT_MEM_ARGS=-Xms512m -Xmx1024m
set DEFAULT_MEM_ARGS=-Xms512m -Xmx768m
【讨论】:
欢迎来到 SO。你确定你回答的问题正确吗?【参考方案15】:在 Windows 中,我解决了这个问题,直接编辑文件 /bin/cassandra.bat,更改“Xms”和“Xmx”JVM_OPTS 参数的值。您可以尝试编辑 /bin/cassandra 文件。在这个文件中,我看到一个注释变量 JVM_OPTS,尝试取消注释并编辑它。
【讨论】:
以上是关于Java 拒绝启动 - 无法为对象堆保留足够的空间的主要内容,如果未能解决你的问题,请参考以下文章