Ho una raccolta di webapp in esecuzione sotto tomcat. Tomcat è configurato per avere fino a 2 GB di memoria usando l'argomento -Xmx.Java Runtime.getRuntime(). Exec() alternative
Molti dei webapps necessità di eseguire un compito che finisce per fare uso del codice seguente:
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(command);
process.waitFor();
...
Il problema che stiamo avendo è legato al modo in cui si sta creato questo "bambino-processo" su Linux (Redhat 4.4 e Centos 5.4).
È a mia conoscenza che una quantità di memoria pari alla quantità utilizzata da Tomcat deve essere libera nel pool di memoria di sistema fisica (non swap) inizialmente per la creazione di questo processo figlio. Quando non abbiamo abbastanza memoria fisica libera, stiamo ottenendo questo:
java.io.IOException: error=12, Cannot allocate memory
at java.lang.UNIXProcess.<init>(UNIXProcess.java:148)
at java.lang.ProcessImpl.start(ProcessImpl.java:65)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
... 28 more
Le mie domande sono:
1) E 'possibile rimuovere il requisito per una quantità di memoria pari al genitore processo di essere libero nella memoria fisica? Sto cercando una risposta che mi permetta di specificare quanta memoria riceve il processo figlio o di consentire a java on linux di accedere alla memoria di swap.
2) Quali sono le alternative a Runtime.getRuntime(). Exec() se non esiste alcuna soluzione al numero 1? Ho potuto solo pensare a due, nessuno dei quali è molto desiderabile. JNI (molto poco desiderabile) o riscrivendo il programma che stiamo chiamando in java e rendendolo il proprio processo che la webapp comunica in qualche modo. Ci devono essere altri.
3) C'è un altro lato di questo problema che non vedo che potrebbe risolvere il problema? Ridurre la quantità di memoria utilizzata da tomcat non è un'opzione. Aumentare la memoria sul server è sempre un'opzione, ma sembra più un cerotto.
server sono in esecuzione Java 6.
EDIT: Vorrei specificare che io non sto cercando una correzione specifica Tomcat. Questo problema può essere visto con qualsiasi delle applicazioni java che abbiamo in esecuzione sul server web (ce ne sono molte). Ho semplicemente usato Tomcat come esempio perché molto probabilmente avrà la maggior parte della memoria assegnata ad esso ed è dove abbiamo effettivamente visto l'errore la prima volta. È un errore riproducibile.
MODIFICA: Alla fine, abbiamo risolto questo problema riscrivendo ciò che stava facendo la chiamata di sistema in java. Sento che siamo stati fortunati ad essere in grado di farlo senza effettuare ulteriori chiamate di sistema. Non tutti i processi saranno in grado di farlo, quindi mi piacerebbe comunque vedere una soluzione reale a questo.
Correlato: http://stackoverflow.com/questions/209875/from-what-linux-kernel-libc-version-is-java-runtime-exec-safe-with-regards-to-m – BalusC
I didn ' In realtà vedo qualcosa in quell'articolo che ha risposto alle mie domande. Un'azione che ho visto è stata "diminuire la quantità di memoria utilizzata dal processo principale" (non è un'opzione per noi), sia con ulimit che con java opts. L'altro era lo stesso della risposta di Luca sopra, che è di fare un processo separato che utilizza meno memoria. Questo è lontano dall'ideale, ma almeno plausibile – twilbrand
Cosa JVM stai usando (Sun, OpenJDK ...?) Questo non aiuta? http://stackoverflow.com/questions/1124771/how-to-solve-java-io-ioexception-error12-cannot-allocate-memory-calling-runt – leonbloy