Java拒绝开始 – 无法为对象堆预留足够的空间
背景
我们有一个大约20个Linux刀片的池。 一些运行Suse,一些运行Redhat。 共享NAS空间,其中包含以下3个文件夹:
- / NAS / app / java – 指向安装Java JDK的符号链接。 目前版本1.5.0_10
- / NAS / app / lib – 一个指向我们应用程序版本的符号链接。
- / NAS / data – 我们的输出被写入的目录
我们所有的机器都有2个处理器(超线程),4GB的物理内存和4GB的交换空间。 我们将每台机器可以在给定时间处理的“工作”数量限制为6个(这个数字可能需要改变,但是这并不会成为当前的问题,所以请暂时忽略它)。
我们的一些工作设置了最大堆大小为512mb,其他一些预留最大堆大小为2048mb。 再一次,我们意识到如果6个作业在堆大小设置为2048的同一台机器上启动,我们可以检查可用内存,但据我们所知,这还没有发生。
问题
有一次,一个作业将立即失败并显示以下消息:
Error occurred during initialization of VM Could not reserve enough space for object heap Could not create the Java virtual machine.
我们过去一直在同一台机器上同时运行太多的作业。 问题很less发生( MAYBE每月一次),我们只是重新启动它,一切都会好的。
这个问题最近变得更糟了。 我们所有要求最大堆大小为2048米的作业几乎每次都会立即失败,需要重新启动几次才能完成。
我们已经去了单独的机器,并尝试手动执行它们,结果相同。
debugging
事实certificate,这个问题只存在于我们的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'给了我们以下两种types的机器:
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---- rb 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的Max Heap)启动一个工作,它会正常启动:
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.
很明显,目前使用的内存是用于缓冲/caching,这就是为什么这么less显示为“免费”的原因。 不清楚的是为什么有一个神奇的1850mb行,其中更高的意味着Java无法启动。
任何解释将不胜感激。
你正在使用一个32位的操作系统,所以你会看到由此造成的总规模的限制。 其他答案更详细地介绍了这一点,所以我会避免重复他们的信息。
最近我们发现服务器的行为是用-Xmx
指定最大堆大小,而用-Xms
指定最小堆大小将导致Java的服务器VM立即尝试分配最大堆大小所需的全部内存。 当然,如果应用程序达到堆大小,那就是您需要的内存量。 但有可能的是,你的应用程序将开始与相对较小的堆, 可能需要在稍后的一个较大的堆。 另外指定最小堆大小将允许您启动您的应用程序从一个较小的堆开始,并逐渐增长堆。
所有这一切都不会帮助你增加你的最大堆大小,但我想这可能会有帮助,所以…
正如其他答复中所build议的那样,问题是虚拟地址空间耗尽的原因。 一个32位的linux用户空间程序通常限制为3GB的AS; 内核使用剩余的1GB(理由:由于前1GB是内核固定映射,因此在服务系统调用时不需要触摸页面表)。
然而,RHEL内核实现了所谓的4GB / 4GB拆分,其中全部4GB AS可用于用户空间进程,代价是运行时间很短(内核位于独立的4GB虚拟AS中)
运行32位操作系统是一个错误; 你应该尽早升级。
我不知道Java是否需要它堆在一个连续的块中,但是如果是这样的话,在32位盒子上要求1.8G的堆听起来像是一个很高的命令。 假设在JVM启动时有大量的地址空间,几乎一半是免费的。
取决于当时加载的其他库,可能没有。 库可以在任何他们喜欢的地方分配内存,所以它可以将地址空间分割得足够大,以至于1.8G在一个块中不可用。
无论如何,Linux 32位只有大约3G地址空间可用。 库和JVM本身使用一些开始。
看来,对于32位服务器来说,有一个JVM的限制是无法克服的(除非你find一个特殊的32位JVM,不要强加2GB或更less的限制)。
服务器端的这个线程有更多的细节,包括几个在32位体系结构上testing过各种JVM的人。 IBM的JVM似乎还允许有100多MB,但是这并不能达到你想要的水平。
http://www.theserverside.com/discussions/thread.tss?thread_id=26347
“真正的”解决scheme是使用64位JVM的64位服务器来获取每个进程大于2GB的堆。 但是,重要的是还要考虑使用64位JVM增加地址大小(而不仅仅是可寻址空间)的影响。 使用less于4GB内存的处理可能会影响性能和内存。
食不备心:做这些工作真的需要2GB的内存吗? 有没有办法修改作业在1.8GB以内运行,这个限制不成问题?
ulimit最大内存大小和虚拟内存设置为无限?
我写了两个应用程序,一个中等大小,另一个相当小。 我会启动中等大小(在Linux,centos),没有任何参数,(Java服务器),它会运行得很好。 但是当我用“java客户端”启动小型应用程序时,它会告诉我不能保留足够的空间,并且不能运行。 我做了实验,并用10m的-Xms和-Xmx,他们都跑了没有抱怨…去图!
这可能离开轨道,但有两件事情需要考虑。 以下两种情况都假定您正在运行一个32位版本的Linux。
Linux上有一个进程大小限制,在CentOS上似乎记得大约是2.5GB,并在内核中configuration(即重新改变)。 一旦将所有JVM代码+ Permgen空间和所有其余的JVM库合并在一起,那么您的进程可能会触发该进程。
第二件事是我遇到的,你可能会用尽地址空间,听起来很奇怪,我知道。 如果运行Glassfish 1.5Gb堆时遇到问题,当它试图编译一个JSP分叉javac它会失败,因为操作系统不能为新创build的进程分配足够的地址空间,即使有12GB的内存。 这里可能有类似的事情发生。
恐怕只有上述两种解决scheme才能升级到64位内核。
希望这有一些用处。
你需要看看升级你的操作系统和Java。 Java 5.0是EOL,但是如果你不能更新到Java 6,你可以使用最新的补丁级别22!
32位的Windows被限制在1.3GB左右,所以你做的最好是1.8。 注意:这是一个持续的内存问题,而且当你的系统运行它的内存空间的时候可能会出现碎片,所以不会让你感到有这个问题。
一个64位的操作系统,没有这个问题,因为它有更多的虚拟空间,你甚至不必升级到64位版本的Java来利用这一点。
顺便说一句,根据我的经验,32位Java 5.0可以比64位Java 5.0更快。 直到很多年之后,Java 6 update 10对于64位才更快。
我将一台机器的内存从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.
问题是我已经为可寻址空间设置了1GB的限制。 增加到2GB解决了这个问题。
-Xms和-Xmx没有效果。
看起来像java试图获得与可用内存成比例的内存,如果不能,则会失败。
要执行的步骤….解决VM初始化期间发生的错误无法为对象堆预留足够的空间无法创buildJava虚拟机。
第1步:减less你以前使用的内存。java -Xms128m -Xmx512m -cp simple.jar
步骤2:从主板上取下RAM一段时间,然后插上并重新启动*可能会释放阻塞堆区的内存.. java -Xms512m -Xmx1024m -cp simple.jar
希望它现在能够正常工作… 🙂
我最近面临这个问题。 我有3个Java应用程序,以1024m或1280m堆大小开始。 Java正在查看swap中的可用空间,如果没有足够的可用内存,则jvm将退出。
要解决这个问题,我不得不结束几个分配了大量虚拟内存的程序。
我正在x86-64 linux上运行一个64位的jvm。
什么是JVM使用? 我知道BEA JRockit的最大堆大小不超过1850mB。 它不会失败,但警告用户,它不会使用超过1850mB。
我不知道为什么有这样的限制,但我知道它存在BEA JRockit。
最好的祝福。
鉴于没有任何其他build议的工作(包括我自己build议的许多事情),以帮助进一步排除故障,你可以尝试运行:
sysctl -a
在SuSE和RedHat机器上看看是否有区别? 我猜这两个分布导致这个默认configuration是不同的。
我正在使用SOA env,从1024到768在setSOADomainENV.cmd
减less了Xmx解决了这个问题。
REM set DEFAULT_MEM_ARGS=-Xms512m -Xmx1024m set DEFAULT_MEM_ARGS=-Xms512m -Xmx768m
在Windows中,我解决了这个问题,直接编辑/bin/cassandra.bat文件,改变“Xms”和“Xmx”JVM_OPTS参数的值。 您可以尝试编辑/ bin / cassandra文件。 在这个文件中,我看到一个注释variablesJVM_OPTS,尝试取消注释并编辑它。