我们拥有大约20个Linux刀片服务器。有些正在运行Suse,有些正在运行Redhat。 ALL共享NAS空间,其中包含以下3个文件夹:
我们所有的机器都有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无法启动。
非常感谢任何解释。
答案 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,尝试取消注释并编辑它。