如何解决"java.io.IOException:error = 12,无法分配内存"调用Runtime #exec()?

And*_*cia 66 java runtime.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");
    }

}
Run Code Online (Sandbox Code Playgroud)

结果是:

[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
Run Code Online (Sandbox Code Playgroud)

系统配置:

[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)
Run Code Online (Sandbox Code Playgroud)

编辑:解决方案 这解决了我的问题,我不知道具体原因:

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
Run Code Online (Sandbox Code Playgroud)

其他信息,免费输出:

[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
Run Code Online (Sandbox Code Playgroud)

小智 36

这是解决方案,但您必须设置:

echo 1 > /proc/sys/vm/overcommit_memory
Run Code Online (Sandbox Code Playgroud)

  • 谨防!将overcommit_memory设置为1,每个malloc()都会成功.当你的内存不足时,Linux将开始随机杀死进程.http://www.win.tue.nl/~aeb/linux/lk/lk-9.html (27认同)

Bri*_*new 18

您的机器的内存配置文件是什么?例如,如果你跑top,你有多少可用记忆?

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

编辑:回复.你的overcommit解决方案,它允许过度使用系统内存,可能允许进程分配(但不使用)比实际可用内存更多的内存.所以我想fork()重复Java进程内存,如下面的评论所述.当然你不使用内存,因为'ls'取代了重复的Java进程.

  • 我认为安德烈是一个"他".这是意大利的男性名字:-) (20认同)
  • 是.我要提到这一点,但我依稀记得现代操作系统将为内存页面实现写时复制,所以我不确定这个 (2认同)

小智 9

Runtime.getRuntime().exec使用与main相同的内存量分配进程.如果您将堆设置为1GB并尝试执行,那么它将为该进程分配另外1GB来运行.

  • 我和Maven有这个问题.我的机器有1GB内存,它运行的是Hudson,Nexus和另一个Maven进程.由于我们在MAVEN_OPTS上错误地设置了-Xms512m,因此Maven进程崩溃了.修复它到-Xms128m解决了它. (2认同)

小智 9

这在Java版本1.6.0_23及更高版本中得到了解决.

有关详细信息,请访问http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7034935


aka*_*okd 8

我遇到了这些链接:

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

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

似乎是一个bug.建议使用spawn()技巧而不是普通的fork()/ exec().


kon*_*o09 8

我用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");
    }
}
Run Code Online (Sandbox Code Playgroud)


Sco*_*Chu 5

如果你查看java.lang.Runtime的源代码,你会看到exec最后调用protected method:execVM,这意味着它使用虚拟内存.因此对于类Unix系统,VM取决于交换空间量+某些物理内存比率.

迈克尔的答案确实解决了你的问题,但它可能(或者说,最终会)导致操作系统在内存分配问题上出现死锁,因为1告诉操作系统不要小心内存分配&0只是猜测并且显然你很幸运,操作系统猜测你可以这个时候有记忆.下次?嗯.....

更好的方法是你试验你的情况并提供一个良好的交换空间并提供更好的物理内存比率和设置值为2而不是1或0.