67

在我的系统上,我无法运行启动进程的简单 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

系统配置:

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

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

回声 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
4

10 回答 10

37

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

echo 1 > /proc/sys/vm/overcommit_memory
于 2010-06-22T13:38:45.317 回答
21

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

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

编辑:回复。您的过度使用解决方案,它允许过度使用系统内存,可能允许进程分配(但不使用)比实际可用更多的内存。所以我猜想fork()复制 Java 进程内存,如下面的评论中讨论的那样。当然,您不使用内存,因为“ls”替换了重复的 Java 进程。

于 2009-07-14T11:27:07.117 回答
9

Runtime.getRuntime().exec为进程分配与主进程相同的内存量。如果您将堆设置为 1GB 并尝试执行,那么它将再分配 1GB 供该进程运行。

于 2010-05-03T23:19:40.107 回答
9

This is solved in Java version 1.6.0_23 and upwards.

See more details at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7034935

于 2012-02-03T10:58:28.337 回答
8

我遇到了这些链接:

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

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

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

于 2009-07-14T11:50:36.180 回答
8

I solved this using 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");
    }
}
于 2011-09-20T21:47:12.540 回答
5

如果你查看java.lang.Runtime的源码,你会看到exec最终调用了受保护的方法:execVM,这意味着它使用了虚拟内存。因此对于类 Unix 系统,VM 取决于交换空间的数量 + 一些物理内存的比例。

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

更好的方法是您试验您的案例并提供良好的交换空间并提供更好的物理内存使用比率并将值设置为 2 而不是 1 或 0。

于 2010-08-01T19:46:45.510 回答
4

过度使用内存

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

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

1 - 总是过度使用。适用于一些科学应用。

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

于 2011-02-21T15:44:38.390 回答
4

您可以使用 Tanuki 包装器使用 POSIX spawn 而不是 fork 来生成进程。http://wrapper.tanukisoftware.com/doc/english/child-exec.html

WrapperManager.exec ()函数是 Java-Runtime.exec() 的替代方法,后者的缺点是使用 fork() 方法,在某些平台上创建新进程可能会变得非常昂贵。

于 2011-08-10T18:45:59.160 回答
4

As weird as this may sound, one work around is to reduce the amount of memory allocated to the 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.

Of course you can try other solutions mentioned here (like over-committing or upgrading to a JVM that has the fix). 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. I'd recommend upgrading the JDK as a long-term stable solution.

于 2012-09-19T13:01:40.640 回答