JDK1.6 Runtime.getRuntime().exec(cmd)执行错误:Cannot allocate memory

最近遇到一个问题,在程序中通过Runtime.getRuntime().exec(cmd)调用Linux中的脚本文件执行脚本抛出了异常:


很是奇怪,应为该程序在其它机器上运行时并没有此异常抛出。
Cannot allocate memory说明无法分配内存。
查看两台机器的运行环境,JVM的配置是相同的,只有机器的配置不同,正常运行的机器是32G内存,异常机器是16G内存,难道真是内存不足造成的?
该程序正常运行峰值最多占用4G内存,JVM开启的最大内存是6644m,理论上应该不会出现内存不足的情况。
最后通过在网上查找,找到了大概的问题所在:Java程序调用外部程序时可能需要分配跟父进程同等大小的内存。
为什么会这么分配内存呢?
看看源码:
java.lang.ProcessImpl

调用了JNI方法,继续查JNI的源码:
Windows JVM 实现:

JVM Linux实现:

linux下的实现(line:57)是调用fork1()函数,就是调用fork指令
fork子进程要传递父进程的所有句柄资源,fork后面紧跟exec,一般copy整个父进程空间的数据到子进程中。
所以fork需要分配与父进程相同的内存。因此,当我调用在程序中调用exec()时,需要一次性分配6644m的内存,系统内存早已不足。

参考:
http://www.w3china.org/blog/more.asp?name=hongrui&id=44142
http://www.myexception.cn/program/1234642.html