Java拒绝启动 - 无法为对象堆保留足够的空间

时间:2009-06-29 13:57:54

标签: java linux memory jvm heap

背景

我们拥有大约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。同样,我们意识到如果在堆大小设置为2048的同一台机器上启动了6个作业,我们可以查看可用内存,但据我们所知,这还没有发生。

问题

有一段时间,作业将立即失败,并显示以下消息:

Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

我们曾经在同一台机器上同时运行太多的作业。问题很少发生( MAYBE 每月一次),我们只是重新启动它,一切都会好的。

最近这个问题变得更糟。我们所有请求最大堆大小为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无法启动。

非常感谢任何解释。

15 个答案:

答案 0 :(得分:21)

您使用的是32位操作系统,因此您将会看到总大小的限制。其他答案已经更详细地介绍了这一点,因此我将避免重复他们的信息。

我最近注意到我们的服务器的一个行为是,使用-Xmx指定最大堆大小而未指定-Xms的最小堆大小将导致Java的服务器VM立即尝试分配所有最大堆大小所需的内存。当然,如果应用程序达到该堆大小,那就是您需要的内存量。但可能的情况是,你的应用程序将以相对较小的堆开始,可能在稍后的某个时候需要更大的堆。另外,指定最小堆大小将允许您以较小的堆启动应用程序,并逐渐增大该堆。

所有这些都无法帮助您增加最大堆大小,但我认为它可能有所帮助,所以......

答案 1 :(得分:15)

正如其他回复中所建议的那样,问题是由虚拟地址空间耗尽引起的。一个32位的linux用户空间程序通常限制为3GB的AS;内核使用剩余的1GB(基本原理:由于前1GB是内核固定映射,因此在提供系统调用时无需触摸页表)。

然而,RHEL内核实现了所谓的4GB / 4GB拆分,其中完整的4GB AS可用于用户空间进程,代价是运营商的轻微开销(内核位于单独的4GB虚拟AS中)

答案 2 :(得分:8)

运行32位操作系统是一个错误;你应该尽早升级。

我不知道Java是否要求其堆在一个连续的块中,但如果确实如此,在32位盒子上要求1.8G的堆听起来就像一个很高的订单。你假设在JVM启动时有一大块地址空间,几乎是其中的一半,是免费的。

根据当时加载的其他库,可能没有。库可以在他们喜欢的任何地方分配内存,因此它可以充分分割您的地址空间,使得一个块中没有1.8G。

无论如何,Linux 32位上只有大约3G地址空间可用。库和JVM本身使用一些来开始。

答案 3 :(得分:4)

对于32位服务器,似乎存在无法克服的JVM限制(除非您发现一个特殊的32位JVM不会施加2GB或更少的限制)。

服务器端的这个主题有更多的细节,包括几个在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内运行,因此这个限制不是问题?

答案 4 :(得分:3)

ulimit最大内存大小和虚拟内存设置为无限制?

答案 5 :(得分:3)

我写了两个应用程序,一个是中等大小,另一个是相当小的。我开火了 中等大小(在linux,centos),没有任何args,(java服务器),它会 跑得很好。但是,当我用“java客户端”启动较小的应用程序时,它会告诉我 我无法保留足够的空间,也不会跑。我进行了实验,并且使用-Xms和-Xmx都使用了10米,并且它们都可以毫无怨言地运行...去图!

答案 6 :(得分:2)

这可能不在轨道上,但有两件事情会浮现在脑海中。以下两种情况都假设您运行的是32位版本的Linux。

linux上有一个进程大小限制,似乎记得在CentOS上大约2.5gb并且在内核中配置(即重新更改)。一旦您添加了所有JVM代码+ Permgen空间和所有其他JVM库,您的进程可能会遇到这种情况。

第二件事是我遇到的事情,你可能已经没有地址空间了,听起来很奇怪。运行带有1.5Gb堆的Glassfish时遇到问题,当它试图编译JSP时,我的forking javac会失败,因为操作系统无法为新创建的进程分配足够的地址空间,即使框中有12GB的内存。可能会有类似的事情发生在这里。

我担心上述两种解决方案只能升级到64位内核。

希望这有一些用处。

答案 7 :(得分:2)

您需要了解升级操作系统和Java。 Java 5.0是EOL,但如果您无法更新到Java 6,则可以使用最新的补丁级别22!

32位Windows仅限于1.3 GB,因此您最好将最大值设置为1.8。注意:这是连续内存的问题,并且随着系统运行,它的内存空间可能会碎片化,所以你不会觉得我有这个问题。

64位操作系统没有这个问题,因为它有更多的虚拟空间,你甚至不必升级到64位版本的java来利用它。

BTW,根据我的经验,32位Java 5.0可能比64位Java 5.0更快。直到很多年后,Java 6更新10才更快64位。

答案 8 :(得分:2)

我将一台机器的内存从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试图获得与可用内存成比例的内存,如果不能,则会失败。

答案 9 :(得分:2)

要执行的步骤......来解决问题 VM初始化期间发生错误 无法为对象堆保留足够的空间 无法创建Java虚拟机。

第1步:减少早先使用的内存.. java -Xms128m -Xmx512m -cp simple.jar

步骤2:从主板上取下RAM一段时间并插上并重新启动 *它可能会释放阻塞堆区域内存.. java -Xms512m -Xmx1024m -cp simple.jar

希望它现在能很好地运作......: - )

答案 10 :(得分:2)

我最近遇到过这个问题。我有3个java应用程序,以1024m或1280m堆大小开始。 Java正在查看swap中的可用空间,如果没有足够的可用内存,jvm将退出。

要解决此问题,我必须结束几个分配了大量虚拟内存的程序。

我使用64位jvm在x86-64 linux上运行。

答案 11 :(得分:1)

JVM使用的是什么? 我知道BEA JRockit的最大堆大小不超过1850mB。它不会失败,但警告用户它不会使用超过1850mB。

我不知道为什么会有这样的限制,但我知道它存在于BEA JRockit。

最好的问候。

答案 12 :(得分:1)

鉴于其他建议都没有奏效(包括我自己建议的很多事情),为了帮助您进一步排查,您可以尝试运行:

sysctl -a

在SuSE和RedHat机器上查看是否有任何差异?我猜这两个分布的默认配置是不同的,这导致了这个。

答案 13 :(得分:1)

我正在使用SOA env,在setSOADomainENV.cmd中将Xmx从1024减少到768解决了这个问题。

REM set DEFAULT_MEM_ARGS=-Xms512m -Xmx1024m
set DEFAULT_MEM_ARGS=-Xms512m -Xmx768m

答案 14 :(得分:-3)

在Windows中,我解决了这个问题,直接编辑文件/bin/cassandra.bat,更改了“Xms”和“Xmx”JVM_OPTS参数的值。您可以尝试编辑/ bin / cassandra文件。在这个文件中,我看到一个注释变量JVM_OPTS,尝试取消注释并编辑它。