web-dev-qa-db-ja.com

Runtime#exec()を呼び出して「Java.io.IOException:error = 12、メモリを割り当てられない」を解決する方法は?

私のシステムでは、プロセスを開始する簡単な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
66
Andrea Francia

あなたのマシンのメモリプロファイルは何ですか?例えばtopを実行すると、空きメモリはどれくらいありますか?

UnixProcessfork()を実行し、OSから十分なメモリを取得していないと思われます(メモリが機能する場合は、プロセスを複製するためにfork()してからexec()は、新しいメモリプロセスでlsを実行しますが、それまでは取得していません)

編集:Re。オーバーコミットソリューションを使用すると、システムメモリのオーバーコミットが可能になり、プロセスが実際に利用できるよりも多くのメモリを割り当てることができます(ただし、使用しません)。以下のコメントで説明されているように、fork()はJavaプロセスメモリを複製します。もちろん、 'ls'が複製を置き換えるため、メモリは使用しません。 Javaプロセス。

18
Brian Agnew

これは解決策ですが、設定する必要があります:

echo 1 > /proc/sys/vm/overcommit_memory
36
Michael

これはJavaバージョン1.6.0_23以降で解決されます。

詳細は http://bugs.Sun.com/bugdatabase/view_bug.do?bug_id=7034935 をご覧ください。

9
Alf Høgemark

Runtime.getRuntime().execは、メインと同じメモリ量でプロセスを割り当てます。ヒープを1GBに設定して実行しようとした場合、そのプロセスを実行するためにさらに1GBが割り当てられます。

9
Attila Bukta

私はこれらのリンクに出くわしました:

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

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

バグのようです。プレーンなfork()/ exec()の代わりにspawn()トリックを使用することをお勧めします。

8
akarnokd

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

Java.lang.Runtimeのソースを調べると、execが最後にprotectedメソッドexecVMを呼び出していることがわかります。これは、仮想メモリを使用することを意味します。したがって、Unixライクシステムの場合、VMはスワップスペースの量+物理メモリの比率に依存します。

マイケルの答えはあなたの問題を解決しましたが、それはO.S.を引き起こす可能性があります(または最終的に言うでしょう)。 1がOSに通知するため、メモリ割り当ての問題でデッドロックが発生するメモリ割り当てにあまり注意しないと0は推測されるだけで、明らかにO.S.今度はメモリがあると思います。次回?うーん.....

より良いアプローチは、あなたのケースを実験し、良いスワップスペースを与え、使用する物理メモリのより良い比率を与え、1または0ではなく2に値を設定することです。

5
Scott Chu

Tanukiラッパーを使用して、forkの代わりにPOSIX spawnでプロセスを生成できます。 http://wrapper.tanukisoftware.com/doc/english/child-exec.html

WrapperManager.exec() 関数は、fork()メソッドを使用する短所があるJava-Runtime.exec()の代替手段です。新しいプロセス。

4
Dan Fabulich

これは奇妙に聞こえるかもしれませんが、回避策の1つは、JVMに割り当てられるメモリの量を減らすことです。 fork()はプロセスとそのメモリを複製するため、JVMプロセスが-Xmxを介して割り当てられたメモリを実際に必要としない場合、gitへのメモリ割り当てが機能します。

もちろん、ここで説明した他のソリューション(オーバーコミットまたは修正されたJVMへのアップグレードなど)を試すこともできます。環境に影響を与えずにすべてのソフトウェアをそのまま保持するソリューションを切望している場合は、メモリを削減してみてください。また、-Xmxを積極的に減らすと、OOMが発生する可能性があることに注意してください。長期安定ソリューションとしてJDKをアップグレードすることをお勧めします。

4
Deepak Bala

overcommit_memory

システムメモリのオーバーコミットを制御し、プロセスが実際に使用可能なメモリよりも多くのメモリを割り当てられるようにします(ただし、使用しません)。

0-ヒューリスティックなオーバーコミット処理。アドレス空間の明らかな超過は拒否されます。典型的なシステムに使用されます。オーバーコミットを許可してスワップの使用量を削減しながら、深刻なワイルド割り当てが失敗することを保証します。このモードでは、rootは少しだけ多くのメモリを割り当てることができます。これがデフォルトです。

1-常にオーバーコミット。一部の科学的用途に適しています。

2-オーバーコミットしないでください。システムの合計アドレス空間コミットは、スワップに物理RAMの構成可能な割合(デフォルトは50)を加えたものを超えることはできません。使用する割合に応じて、ほとんどの場合、これは既に割り当てられたメモリを使用しようとしてもプロセスが強制終了されないことを意味しますが、必要に応じてメモリ割り当てでエラーを受け取ります。

4
ricardofunke