我有一组在 tomcat 下运行的 webapps。使用 -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 中所做的事情解决了这个问题。我觉得我们很幸运能够在不进行额外系统调用的情况下做到这一点。并非所有进程都能够做到这一点,所以我仍然希望看到一个实际的解决方案。