【发布时间】:2011-02-22 01:08:44
【问题描述】:
我有一组在 tomcat 下运行的 web 应用程序。使用 -Xmx 参数将 Tomcat 配置为拥有多达 2 GB 的内存。
许多 web 应用程序需要执行最终使用以下代码的任务:
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(command);
process.waitFor();
...
我们遇到的问题与在 Linux(Redhat 4.4 和 Centos 5.4)上创建这个“子进程”的方式有关。
据我了解,最初需要在物理(非交换)系统内存池中释放与 tomcat 使用的内存量相等的内存量,才能创建此子进程。当我们没有足够的可用物理内存时,我们会得到:
java.io.IOException: error=12, Cannot allocate memory
at java.lang.UNIXProcess.<init>(UNIXProcess.java:148)
at java.lang.ProcessImpl.start(ProcessImpl.java:65)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
... 28 more
我的问题是:
1) 是否可以取消对等于父进程在物理内存中空闲的内存量的要求?我正在寻找一个可以让我指定多少的答案子进程获得的内存或允许 linux 上的 java 访问交换内存。
2) 如果不存在#1 的解决方案,Runtime.getRuntime().exec() 的替代方案是什么? 我只能想到两个,这两个都不是很理想。 JNI(非常不可取)或重写我们在 java 中调用的程序并使其成为 webapp 以某种方式与之通信的自己的进程。必须有其他人。
3) 我没有看到这个问题的另一面可以解决它吗? 降低 tomcat 使用的内存量不是一种选择。增加服务器上的内存始终是一种选择,但似乎更像是一种创可贴。
服务器正在运行 java 6。
编辑:我应该指定我不是在寻找特定于 tomcat 的修复程序。我们在网络服务器上运行的任何 java 应用程序都可以看到这个问题(有多个)。我只是以 tomcat 为例,因为它很可能分配给它的内存最多,而且这是我们第一次真正看到错误的地方。这是一个可重现的错误。
编辑:最后,我们通过重写系统调用在 java 中所做的事情解决了这个问题。我觉得我们很幸运能够在不进行额外系统调用的情况下做到这一点。并非所有进程都能够做到这一点,所以我仍然希望看到一个实际的解决方案。
【问题讨论】:
-
我实际上并没有在那篇文章中看到任何回答我问题的内容。我在那里看到的一个动作是“减少父进程使用的内存量”(对我们来说不是一个选项),无论是使用 ulimit 还是 java opts。另一个与上面卢克的回答相同,即制作一个使用更少内存的单独进程。这远非理想,但至少是合理的
-
您使用的是什么 JVM(Sun、OpenJDK...?)这没有帮助吗? stackoverflow.com/questions/1124771/…
-
这是上面提到的 linux 操作系统上的 Sun JVM。在那篇文章中,原始发帖人说他用“echo 0 > /proc/sys/vm/overcommit_memory”修复了它,并请人解释原因。从来没有人这样做过。在我有更多关于它的信息之前,我对使用这种方法持怀疑态度。谷歌搜索对我没有帮助。这个命令可能会回答我的 #1 或 #3,但我正在寻找人来解释它在做什么以及使用它的优点/缺点。
-
那么,你最后做了什么?我认为这是一个很好的问题。为了我们其他人的利益,请提供您的解决方案(尝试?)来解决这个问题。
标签: java tomcat memory-management runtime.exec