我有一组在Tomcat下运行的Web应用程序。 Tomcat已使用-Xmx参数配置了多达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中重新编写我们调用的程序并使其成为自己的进程,Web应用程序以某种方式与其通信。必定还有其他替代方法。
3)这个问题是否有我没有看到的另一面可以潜在地修复它?降低Tomcat使用的内存量不是一个选项。增加服务器的内存始终是一种选择,但似乎更像是一个临时措施。
服务器正在运行Java 6。
编辑:我应该说明我不是在寻找特定于Tomcat的解决方案。我们在Web服务器上运行的任何Java应用程序都可能遇到此问题(有多个)。我仅仅是以Tomcat作为一个例子,因为它可能会分配最多的内存,而且它是我们第一次看到错误的地方。这是一个可复现的错误。
编辑:最终,我们通过在Java中重新编写系统调用的操作来解决了这个问题。我觉得我们很幸运,能够在不进行额外系统调用的情况下做到这一点。并不是所有进程都能够做到这一点,因此我仍然希望看到这个问题的实际解决方案。