2009-07-14 6 views
65

Sul mio sistema non riesco a eseguire una semplice applicazione Java che avvia un processo. Non so come risolvere.Come risolvere "java.io.IOException: error = 12, Can not allocate memory" chiamando Runtime # exec()?

Potrebbe darmi qualche suggerimento su come risolvere?

Il programma è il seguente:

[[email protected] 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 è:

[[email protected] 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:

[[email protected] 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) 
[[email protected] sisma-acquirer]# cat /etc/fedora-release 
Fedora release 10 (Cambridge) 

EDIT: Soluzione Questo risolve il mio problema, io non so esattamente perché:

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:

[[email protected] sisma-acquirer]# free 
      total  used  free  shared buffers  cached 
Mem:  1033456  588548  444908   0  51704  188292 
-/+ buffers/cache:  348552  684904 
Swap:  2031608   0 2031608 
+0

È un errore nella versione di Linux o si verificano problemi di privilegi. Potresti cercare in UnixProcess: 164 nella fonte per scoprire che cosa tenta di allocare. – akarnokd

+1

Puoi sempre provare il sole jdk – wds

+0

Ho pubblicato un link a una libreria gratuita che risolve il tuo problema ma un moderatore ha cancellato la mia risposta senza spiegazioni. A beneficio della comunità, gli faccio un altro tentativo come commento: il tuo problema di memoria è risolto da Yajsw che su Linux usa le chiamate a una libreria C per la creazione del processo. Leggi qui: http://sourceforge.net/projects/yajsw/forums/forum/810311/topic/4423982 – kongo09

risposta

16

Qual è il profilo di memoria della macchina? per esempio. se esegui top, quanta memoria libera hai?

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 fino a che)

MODIFICA: Re. la tua soluzione overcommit, permette l'overcommitting della memoria di sistema, permettendo eventualmente ai processi di allocare (ma non utilizzare) più memoria di quella effettivamente disponibile. Quindi immagino che il fork() duplica la memoria del processo Java come discusso nei commenti qui sotto. Ovviamente non si usa la memoria poiché "ls" sostituisce il processo Java duplicato.

+0

Una volta ho letto che la chiamata a fork() in realtà duplica l'intera memoria del processo attualmente in esecuzione. È ancora vero? Se hai un programma java con una memoria da 1,2 GB e 2 GB totali, suppongo che fallirà? – akarnokd

+2

Sì. Stavo per dirlo, ma ricordo vagamente che i sistemi operativi moderni implementeranno la copia in scrittura per le pagine di memoria, quindi non sono sicuro di questo –

+0

Se esegue l'app con le impostazioni predefinite, non dovrebbe essere un problema per duplicare 64 MB di memoria immagino. – akarnokd

9

Runtime.getRuntime().exec alloca il processo con la stessa quantità di memoria del principale. Se si dispone di heap impostato su 1 GB e si tenta di eseguire exec, verrà assegnato un altro 1 GB per l'esecuzione di tale processo.

+2

Ho avuto questo problema con Maven. La mia macchina aveva una memoria da 1 GB e stava eseguendo Hudson, Nexus e un altro processo Maven. Il processo Maven si è arrestato in modo anomalo poiché abbiamo impostato -Xms512m per errore su MAVEN_OPTS. Risolvendolo a -Xms128m risolto. –

33

Questa è la soluzione, ma è necessario impostare:

echo 1 > /proc/sys/vm/overcommit_memory 
+24

Attenzione! Con overcommit_memory impostato su 1 ogni malloc() avrà successo. Linux inizierà a uccidere i processi in modo casuale quando la memoria è esaurita. http://www.win.tue.nl/~aeb/linux/lk/lk-9.html –

+0

È possibile limitare questo per processo, anziché a livello di sistema? –

+1

Utilizzo di questa soluzione in sviluppo in una scatola di Vagrant. –

5

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

La risposta di Michael ha risolto il problema ma potrebbe (o dire, alla fine) causare gli O.S. deadlock nel problema di allocazione della memoria da 1 a dire agli O.S. meno attento dell'allocazione della memoria & 0 è solo una supposizione che siate certi che voi siete fortunati che il O.S. Immagino che tu possa avere memoria QUESTA VOLTA. La prossima volta? Hmm .....

Meglio approccio è che si sperimenta il vostro caso & dare un buon spazio di swap & dare un miglior rapporto di memoria fisica utilizzata & valore impostato a 2 invece di 1 o 0.

4

overcommit_memory

Controlla l'overcommit della memoria di sistema, consentendo eventualmente ai processi di allocare (ma non utilizzare) più memoria di quella effettivamente disponibile.

0 - Gestione euristica del sovraccarico. I casi di overcommits evidenti nello spazio degli indirizzi sono rifiutati. Utilizzato per un sistema tipico. Assicura che un'assegnazione seriamente fallita fallisce consentendo al overcommit di ridurre l'utilizzo dello swap. root è autorizzato ad allocare leggermente più memoria in questa modalità. Questo è l'impostazione predefinita.

1 - Sempre overcommit. Adeguato per alcune applicazioni scientifiche.

2 - Non eseguire l'overcommit. Lo spazio totale di indirizzamento per il sistema non può superare lo swap più una percentuale configurabile (il valore predefinito è 50) di RAM fisica. A seconda della percentuale che si utilizza, nella maggior parte delle situazioni ciò significa che un processo non verrà ucciso mentre si tenta di utilizzare la memoria già allocata, ma riceverà gli errori sull'allocazione della memoria come appropriato.

4

È possibile utilizzare il wrapper Tanuki per generare un processo con spawn POSIX anziché fork. 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.

+0

Il wrapper Tanuki è piuttosto impressionante. Sfortunatamente, il 'WrapperManager' fa parte della Professional Edition, che è piuttosto costosa se questa è l'unica cosa di cui hai bisogno. Conosci qualche alternativa gratuita? – kongo09

+0

@ kongo09 È disponibile anche come parte dell'edizione community gratuita (GPLv2). Puoi anche scaricare la fonte e usarla nei prodotti GPL. –

+0

Non penso che questo faccia parte dell'edizione comunitaria. Se si prova un test rapido, si otterrà la seguente eccezione: 'Eccezione nel thread" main "org.tanukisoftware.wrapper.WrapperLicenseError: Richiede l'Edizione Professional. – kongo09

8

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

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

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

+0

Qualsiasi idea se si applica a OpenJDK o equivalenti JVM non Sun ? –

+0

Non riesco a ottenere questo problema dopo l'aggiornamento a 1.6.0_37-b06 .. Ancora confuso circa la correzione del bug .. Quindi quanta memoria jvm si alloca a 'Runtime.exec'? –

+0

Punto eccellente. L'aggiornamento di JVM risolve il problema poiché ora utilizza una chiamata di sistema diversa (più leggera). – neesh

4

quanto strano possa sembrare, un lavoro intorno è quello di ridurre la quantità di memoria allocata alla JVM. Dato che fork() duplica il processo e la sua memoria, se il tuo processo JVM non ha realmente bisogno della quantità di memoria assegnata tramite -Xmx, l'allocazione della memoria su git funzionerà.

Ovviamente puoi provare altre soluzioni menzionate qui (come l'eccesso di commit o l'aggiornamento a una JVM che ha la correzione). Puoi provare a ridurre la memoria se sei alla disperata ricerca di una soluzione che mantenga intatto tutto il software senza alcun impatto sull'ambiente. Ricorda inoltre che ridurre -Xmx in modo aggressivo può causare OOM. Consiglierei l'aggiornamento del JDK come soluzione stabile a lungo termine.

0

Semplice uccisione ha funzionato per me.

fare

free -m

per controllare la quantità di memoria disponibile.

Uccidere alcuni dei lavori che non sono necessari.

Problemi correlati