简体   繁体   English

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

[英]How to solve “java.io.IOException: error=12, Cannot allocate memory” calling Runtime#exec()?

On my system I can't run a simple Java application that start a process. 在我的系统上,我无法运行启动进程的简单Java应用程序。 I don't know how to solve. 我不知道该怎么解决。

Could you give me some hints how to solve? 你能给我一些如何解决的提示吗?

The program is: 该计划是:

[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");
    }

}

The result is: 结果是:

[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 of the system: 系统配置:

[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)

EDIT: Solution This solves my problem, I don't know exactly why: 编辑:解决方案这解决了我的问题,我不知道具体原因:

echo 0 > /proc/sys/vm/overcommit_memory echo 0> / proc / sys / vm / overcommit_memory

Up-votes for who is able to explain :) 向谁投票能够解释:)

Additional informations, top output: 其他信息,最高输出:

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

Additional informations, free output: 其他信息,免费输出:

[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

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

echo 1 > /proc/sys/vm/overcommit_memory

What's the memory profile of your machine ? 您的机器的内存配置文件是什么? eg if you run top , how much free memory do you have ? 例如,如果你跑到top ,你有多少可用内存?

I suspect UnixProcess performs a fork() and it's simply not getting enough memory from the OS (if memory serves, it'll fork() to duplicate the process and then exec() to run the ls in the new memory process, and it's not getting as far as that) 我怀疑UnixProcess执行fork()并且它根本没有从操作系统获得足够的内存(如果内存服务,它将fork()复制进程,然后exec()在新的内存进程中运行ls,并且它是没那么远)

EDIT: Re. 编辑:回复。 your overcommit solution, it permits overcommitting of system memory, possibly allowing processes to allocate (but not use) more memory than is actually available. 你的overcommit解决方案,它允许过度使用系统内存,可能允许进程分配(但不使用)比实际可用内存更多的内存。 So I guess that the fork() duplicates the Java process memory as discussed in the comments below. 所以我猜fork()复制了Java进程内存,如下面的评论所述。 Of course you don't use the memory since the 'ls' replaces the duplicate Java process. 当然你不使用内存,因为'ls'取代了重复的Java进程。

Runtime.getRuntime().exec allocates the process with the same amount of memory as the main. Runtime.getRuntime().exec使用与main相同的内存量来分配进程。 If you had you heap set to 1GB and try to exec then it will allocate another 1GB for that process to run. 如果您将堆设置为1GB并尝试执行,那么它将为该进程分配另外1GB来运行。

This is solved in Java version 1.6.0_23 and upwards. 这在Java版本1.6.0_23及更高版本中得到了解决。

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

I came across these links: 我遇到了这些链接:

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

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

Seems to be a bug. 似乎是一个bug。 Usage of a spawn() trick instead of the plain fork()/exec() is advised. 建议使用spawn()技巧而不是普通的fork()/ exec()。

I solved this using JNA: https://github.com/twall/jna 我用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");
    }
}

If you look into the source of java.lang.Runtime, you'll see exec finally call protected method: execVM, which means it uses Virtual memory. 如果你查看java.lang.Runtime的源代码,你会看到exec最后调用protected method:execVM,这意味着它使用虚拟内存。 So for Unix-like system, VM depends on amount of swap space + some ratio of physical memory. 因此对于类Unix系统,VM取决于交换空间量+某些物理内存比率。

Michael's answer did solve your problem but it might (or to say, would eventually) cause the OS deadlock in memory allocation issue since 1 tell OS less careful of memory allocation & 0 is just guessing & obviously that you are lucky that OS guess you can have memory THIS TIME. 迈克尔的答案确实解决了你的问题,但它可能(或者说,最终会)导致操作系统在内存分配问题上出现死锁,因为1告诉操作系统不要小心内存分配&0只是猜测并且显然你很幸运,操作系统猜测你可以这个时候有记忆。 Next time? 下次? Hmm..... 嗯.....

Better approach is that you experiment your case & give a good swap space & give a better ratio of physical memory used & set value to 2 rather than 1 or 0. 更好的方法是你试验你的情况并提供一个良好的交换空间并提供更好的物理内存比率和设置值为2而不是1或0。

As weird as this may sound, one work around is to reduce the amount of memory allocated to the JVM. 听起来很奇怪,一个解决方法是减少分配给JVM的内存量。 Since fork() duplicates the process and its memory, if your JVM process does not really need as much memory as is allocated via -Xmx, the memory allocation to git will work. 由于fork()复制了进程及其内存,如果你的JVM进程并不真正需要通过-Xmx分配的内存,那么git的内存分配就可以了。

Of course you can try other solutions mentioned here (like over-committing or upgrading to a JVM that has the fix). 当然,您可以尝试此处提到的其他解决方案(例如过度提交或升级到具有此修复程序的JVM)。 You can try reducing the memory if you are desperate for a solution that keeps all software intact with no environment impact. 如果您急需一个能够保持所有软件完整且不受环境影响的解决方案,您可以尝试减少内存。 Also keep in mind that reducing -Xmx aggressively can cause OOMs. 还要记住,减少-Xmx会积极地导致OOM。 I'd recommend upgrading the JDK as a long-term stable solution. 我建议将JDK升级为长期稳定的解决方案。

overcommit_memory overcommit_memory

Controls overcommit of system memory, possibly allowing processes to allocate (but not use) more memory than is actually available. 控制系统内存的过度使用,可能允许进程分配(但不使用)比实际可用内存更多的内存。

0 - Heuristic overcommit handling. 0 - 启发式过度使用处理。 Obvious overcommits of address space are refused. 地址空间的明显过度使用被拒绝。 Used for a typical system. 用于典型系统。 It ensures a seriously wild allocation fails while allowing overcommit to reduce swap usage. 它确保严重的疯狂分配失败,同时允许过度使用以减少交换使用。 root is allowed to allocate slighly more memory in this mode. root允许在这种模式下分配更多的内存。 This is the default. 这是默认值。

1 - Always overcommit. 1 - 总是过度使用。 Appropriate for some scientific applications. 适合某些科学应用。

2 - Don't overcommit. 2 - 不要过度使用。 The total address space commit for the system is not permitted to exceed swap plus a configurable percentage (default is 50) of physical RAM. 系统的总地址空间提交不允许超过交换加上物理RAM的可配置百分比(默认值为50)。 Depending on the percentage you use, in most situations this means a process will not be killed while attempting to use already-allocated memory but will receive errors on memory allocation as appropriate. 根据您使用的百分比,在大多数情况下,这意味着在尝试使用已分配的内存时不会终止进程,但会在适当时收到内存分配错误。

You can use the Tanuki wrapper to spawn a process with POSIX spawn instead of fork. 你可以使用Tanuki包装器来生成一个带有POSIX spawn而不是fork的进程。 http://wrapper.tanukisoftware.com/doc/english/child-exec.html http://wrapper.tanukisoftware.com/doc/english/child-exec.html

The WrapperManager.exec() function is an alternative to the Java-Runtime.exec() which has the disadvantage to use the fork() method, which can become on some platforms very memory expensive to create a new process. WrapperManager.exec()函数是Java-Runtime.exec()的替代方法,它的缺点是使用fork()方法,在某些平台上创建新进程的内存非常昂贵。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 hadoop无法分配内存java.io.IOException:错误= 12 - hadoop cannot allocate memory java.io.IOException: error=12 Runtime.getRuntime().exec() 导致 java.io.IOException: Cannot run program... no such file or directory - Runtime.getRuntime().exec() results in java.io.IOException: Cannot run program ... no such file or directory java.io.IOException: 无法运行程序“...”: java.io.IOException: error=2, No such file or directory - java.io.IOException: Cannot run program “…”: java.io.IOException: error=2, No such file or directory 启动tomcat 5.5时如何解决这个“java.io.IOException:无法重命名原始文件”? - How to solve this “java.io.IOException: Cannot rename original file” when starting tomcat 5.5? 如何解决错误 java.io.IOException: Input/output error in nativeavailable for Serial Communication? - How to solve error java.io.IOException: Input/output error in nativeavailable for Serial Communication? 如何解决java.io.IOException:使用apache POI读取Excel文件时出现读取错误 - How to solve java.io.IOException: Read error when reading Excel file using apache POI java.io.IOException:无法运行程序“ scala”:CreateProcess错误= 2, - java.io.IOException: Cannot run program “scala”: CreateProcess error=2, java.io.IOException:无法运行程序“ C:\\ AutoIt \\ ModenaAutoIt.exe”:java.io.IOException:error = 2,没有此类文件或目录 - java.io.IOException: Cannot run program “C:\AutoIt\ModenaAutoIt.exe”: java.io.IOException: error=2, No such file or directory 无法运行程序java.io.IOException - Cannot run program java.io.IOException java.io.IOException:无法运行程序“/usr/bin/sh”:java.io.IOException:error=2,没有那个文件或目录 - java.io.IOException: Cannot run program “/usr/bin/sh”: java.io.IOException: error=2, No such file or directory
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM