背景
我们有大约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。同样,我们意识到如果在堆大小设置为2048的情况下在同一台机器上启动6个作业,我们可能会超过可用内存,但据我们所知,这种情况尚未发生。
问题
偶尔会有一个作业立即失败,并显示以下消息:
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无法启动。
任何解释都将不胜感激。