Come risolvere “java.io.IOException: error = 12, non può allocare memoria” chiamando Runtime # exec ()?

StackOverflow https://stackoverflow.com/questions/1124771

  •  13-09-2019
  •  | 
  •  

Domanda

Sul mio sistema non riesco a eseguire una semplice applicazione Java che avvia un processo. Io non so come risolvere.

Potreste darmi qualche suggerimento su come risolvere?

Il programma è il seguente:

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

}

Il risultato è:

[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

Configurazione del sistema:

[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: Soluzione Questo risolve il mio problema, non so esattamente il motivo:

echo 0> / proc / sys / vm / overcommit_memory

Up-voti per chi è in grado di spiegare:)

Informazioni aggiuntive, uscita superiore:

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

Informazioni aggiuntive, uscita libera:

[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
È stato utile?

Soluzione

Qual è il profilo di memoria della vostra macchina? per esempio. se si esegue top, la quantità di memoria avete?

Ho il sospetto UnixProcess esegue un fork() e non è semplicemente ottenere abbastanza memoria dal sistema operativo (se la memoria non serve, sarà fork() per duplicare il processo e poi exec() per eseguire i ls nel nuovo processo di memoria, e non è sempre come qualora tale)

EDIT: Re. la soluzione overcommit, permette overcommitting di memoria di sistema, che possono consentire processi di allocare (ma non usa) più memoria di quella effettivamente disponibile. Quindi credo che la fork() duplica la memoria processo Java come discusso nei commenti qui sotto. Naturalmente non si utilizza la memoria a partire dagli ls 'sostituisce il processo di Java duplicato.

Altri suggerimenti

Questa è la soluzione, ma è necessario impostare:

echo 1 > /proc/sys/vm/overcommit_memory

Questa è risolto in Java versione 1.6.0_23 e verso l'alto.

Vedi i dettagli a http://bugs.sun.com/bugdatabase/view_bug.do?bug_id = 7034935

Runtime.getRuntime().exec alloca il processo con la stessa quantità di memoria, come principale. Se tu avessi si mucchio di impostare a 1 GB e cercare di exec allora stanzierà altri 1GB per quel processo per l'esecuzione.

mi sono imbattuto in questi link:

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

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

Sembra essere un bug. Si consiglia l'utilizzo di uno spawn () trucco al posto della forcella pianura () / exec ().

Ho risolto questo con 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");
    }
}

Se si guarda nella fonte di java.lang.Runtime, vedrete exec finalmente chiamare metodo protetto: execVM, il che significa che utilizza la memoria virtuale. Quindi, per il sistema Unix-like, VM dipende dalla quantità di spazio di swap + qualche rapporto tra memoria fisica.

risposta

di Michael ha risolto il problema, ma potrebbe (o per dire, sarebbe poi) sì che l'O.S. stallo in tema di allocazione di memoria dal 1 dicono O.S. meno attenti di allocazione di memoria e 0 è solo indovinare e, ovviamente, che si è fortunati che O.S. Immagino si può avere la memoria QUESTO MOMENTO. La prossima volta? Hmm .....

Una migliore approccio è che si sperimenta il vostro caso e dare un buon spazio di swap e dare un miglior rapporto di memoria fisica utilizzata e impostare il valore a 2 invece di 1 o 0.

overcommit_memory

Controlli overcommit della memoria di sistema, che possono consentire processi di allocare (ma non usa) più memoria di quella effettivamente disponibile.

0 - movimentazione overcommit euristica. overcommits evidenti di spazio di indirizzamento vengono rifiutati. Utilizzato per un sistema tipico. Assicura una dotazione seriamente selvaggio fallisce, consentendo overcommit per ridurre l'utilizzo di swap. root può allocare leggermente più memoria in questa modalità. Questa è l'impostazione predefinita.

1 - overcommit sempre. Adeguato per alcune applicazioni scientifiche.

2 - Non overcommit. Lo spazio totale indirizzo impegnarsi per il sistema non è consentito superare di swap più una percentuale configurabile (di default è 50) di RAM fisica. A seconda della percentuale si utilizza, nella maggior parte delle situazioni questo significa un processo non sarà ucciso durante il tentativo di utilizzare la memoria già allocata ma riceveranno errori di allocazione di memoria a seconda del caso.

È possibile utilizzare il wrapper Tanuki per deporre le uova un processo con POSIX uova invece di forchetta. http://wrapper.tanukisoftware.com/doc/english/child-exec.html

  

Il WrapperManager.exec () funzione è in alternativa alla Java Runtime.exec () che ha lo svantaggio di utilizzare il metodo forcella (), che può diventare su alcune piattaforme molto costosi memoria per creare un nuovo processo.

Per quanto strano possa sembrare, un lavoro intorno è quello di ridurre la quantità di memoria allocata alla JVM. Poiché fork () duplica il processo e la sua memoria, se il processo JVM non realmente bisogno tanto memoria, come viene allocata tramite -Xmx, l'allocazione di memoria per GIT funzionerà.

Naturalmente è possibile provare altre soluzioni di cui qui (come over-commettere o l'aggiornamento a una JVM che ha la correzione). Si può provare a ridurre la memoria, se siete alla disperata ricerca di una soluzione che mantiene intatto tutto il software senza alcun impatto ambientale. Anche tenere a mente che la riduzione -Xmx aggressivo può causare Ooms. Mi consiglia di aggiornare il JDK come una soluzione stabile a lungo termine.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top