Java Runtime.getRuntime().exec() alternatives
我有一个在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中所做的工作来解决这个问题。我觉得我们很幸运能够在不进行额外系统调用的情况下做到这一点。并非所有流程都能够做到这一点,所以我仍然希望看到一个实际的解决方案。