如何解决“java.io.IOException:错误= 12,无法分配内存”调用运行时#exec()?

在我的系统上,我无法运行启动进程的简单Java应用程序。 我不知道如何解决。

你能给我一些提示如何解决?

该计划是:

[root@newton sisma-acquirer]# cat prova.java import java.io.IOException; public class prova { public static void main(String[] args) throws IOException { Runtime.getRuntime().exec("ls"); } } 

结果是:

 [root@newton sisma-acquirer]# javac prova.java && java -cp . prova Exception in thread "main" java.io.IOException: Cannot run program "ls": java.io.IOException: error=12, Cannot allocate memory at java.lang.ProcessBuilder.start(ProcessBuilder.java:474) at java.lang.Runtime.exec(Runtime.java:610) at java.lang.Runtime.exec(Runtime.java:448) at java.lang.Runtime.exec(Runtime.java:345) at prova.main(prova.java:6) Caused by: java.io.IOException: java.io.IOException: error=12, Cannot allocate memory at java.lang.UNIXProcess.<init>(UNIXProcess.java:164) at java.lang.ProcessImpl.start(ProcessImpl.java:81) at java.lang.ProcessBuilder.start(ProcessBuilder.java:467) ... 4 more 

系统的configuration:

 [root@newton sisma-acquirer]# java -version java version "1.6.0_0" OpenJDK Runtime Environment (IcedTea6 1.5) (fedora-18.b16.fc10-i386) OpenJDK Client VM (build 14.0-b15, mixed mode) [root@newton sisma-acquirer]# cat /etc/fedora-release Fedora release 10 (Cambridge) 

编辑:解决scheme这解决了我的问题,我不知道为什么:

echo 0> / proc / sys / vm / overcommit_memory

谁可以解释:)的投票

其他信息,顶部输出:

 top - 13:35:38 up 40 min, 2 users, load average: 0.43, 0.19, 0.12 Tasks: 129 total, 1 running, 128 sleeping, 0 stopped, 0 zombie Cpu(s): 1.5%us, 0.5%sy, 0.0%ni, 94.8%id, 3.2%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 1033456k total, 587672k used, 445784k free, 51672k buffers Swap: 2031608k total, 0k used, 2031608k free, 188108k cached 

其他信息,免费输出:

 [root@newton sisma-acquirer]# free total used free shared buffers cached Mem: 1033456 588548 444908 0 51704 188292 -/+ buffers/cache: 348552 684904 Swap: 2031608 0 2031608 

什么是你的机器的内存configuration文件? 例如,如果你跑得top ,你有多less空闲的记忆?

我怀疑UnixProcess执行fork() ,它只是没有得到足够的内存从操作系统(如果内存服务,它将fork()复制进程,然后exec()在新的内存进程中运行ls,它没有达到那么远)

编辑:再。 您的overcommit解决scheme,它允许系统内存的过度使用,可能允许进程分配(但不使用)比实际可用的更多的内存。 所以我猜, fork()复制了Java进程内存,正如下面的注释中所讨论的那样。 当然你不用内存,因为'ls'代替了重复的Java进程。

这是解决scheme,但你必须设置:

 echo 1 > /proc/sys/vm/overcommit_memory 

这在Java版本1.6.0_23及更高版本中得以解决。

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7034935查看更多详情;

Runtime.getRuntime().exec进程分配相同数量的内存。 如果你把堆设置为1GB,并尝试执行,那么它将分配另一个1GB的进程运行。

我遇到了这些链接:

http://mail.openjdk.java.net/pipermail/core-libs-dev/2009-May/001689.html

http://www.nabble.com/Review-request-for-5049299-td23667680.html

似乎是一个错误。 build议使用spawn()技巧而不是简单的fork()/ exec()。

我使用JNA解决了这个问题: https : //github.com/twall/jna

 import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Platform; public class prova { private interface CLibrary extends Library { CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class); int system(String cmd); } private static int exec(String command) { return CLibrary.INSTANCE.system(command); } public static void main(String[] args) { exec("ls"); } } 

如果查看java.lang.Runtime的源代码,则会看到exec最后调用protected方法:execVM,这意味着它使用虚拟内存。 所以对于类Unix系统,VM依赖于交换空间量+一些物理内存的比例。

迈克尔的答案确实解决了你的问题,但它可能(或说,最终)会导致内存分配问题的操作系统死锁,因为1告诉操作系统不太注意内存分配和0只是猜测,显然你很幸运,操作系统猜你可以有这个时间的记忆。 下次? 嗯…..

更好的方法是,你实验你的情况,给一个很好的交换空间,并提供一个更好的物理内存使用率和设置值2而不是1或0。

overcommit_memory

控制系统内存的过度使用,可能允许进程分配(但不使用)比实际可用的更多的内存。

0 – 启发式overcommit处理。 地址空间明显过量使用被拒绝。 用于典型的系统。 它确保严重的野外分配失败,同时允许overcommit以减less交换使用。 root允许在这种模式下分配更多的内存。 这是默认的。

1 – 总是过度使用。 适合一些科学应用。

2 – 不要过度使用。 系统的总地址空间提交不允许超过交换分区,加上物理RAM的可configuration百分比(默认值为50)。 根据您使用的百分比,在大多数情况下,这意味着在尝试使用已分配的内存时,进程不会被终止,但会在适当情况下在内存分配时收到错误。

你可以使用Tanuki包装来产生一个POSIX spawn而不是fork的进程。 http://wrapper.tanukisoftware.com/doc/english/child-exec.html

WrapperManager.exec()函数是Java-Runtime.exec()的一个替代方法,它使用fork()方法是有缺点的,它可以在某些平台上变得非常昂贵,以创build一个新进程。

听起来很奇怪,解决办法之一是减less分配给JVM的内存量。 由于fork()复制了进程和内存,如果你的JVM进程不需要通过-Xmx分配的内存,那么git的内存分配就可以工作。

当然,您可以尝试其他解决scheme(比如过度提交或升级到具有修补程序的JVM)。 如果您迫切希望能够保持所有软件完好无损,并且不受环境影响,则可以尝试减less内存。 另外请记住,减less-Xmx积极可以导致OOM。 我build议升级JDK作为一个长期稳定的解决scheme。

简单的杀人为我工作。

free -m

检查有多less内存可用。

杀死一些不需要的工作。