Limite di thread singolo processo Java basso in Red Hat Linux
Domanda
Riscontro un problema su una macchina di prova che esegue Red Hat Linux (la versione del kernel è 2.4.21-37.ELsmp) utilizzando Java 1.6 (1.6.0_02 o 1.6.0_04). Il problema è che, una volta creato un certo numero di thread in un singolo gruppo di thread, il sistema operativo non è disposto o non è più in grado di crearlo.
Questo sembra essere specifico per la creazione di thread Java, in quanto il programma C thread-limit è stato in grado di creare circa 1,5k thread. Inoltre, ciò non accade con una JVM Java 1.4 ... può creare oltre 1.4k thread, sebbene siano ovviamente gestiti in modo diverso rispetto al sistema operativo.
In questo caso, il numero di thread che sta tagliando è di soli 29 thread. Questo è testabile con un semplice programma Java che crea solo thread fino a quando non viene visualizzato un errore e quindi stampa il numero di thread creati. L'errore è un
java.lang.OutOfMemoryError: unable to create new native thread
Questo sembra non essere influenzato da cose come il numero di thread in uso da altri processi o utenti o la quantità totale di memoria che il sistema sta usando in quel momento. Le impostazioni JVM come Xms, Xmx e Xss non sembrano cambiare nulla (il che è previsto, considerando che il problema sembra riguardare la creazione di thread del sistema operativo nativo).
L'output di " ulimit -a " è il seguente:
core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited file size (blocks, -f) unlimited max locked memory (kbytes, -l) 4 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 7168 virtual memory (kbytes, -v) unlimited
Il limite del processo dell'utente non sembra essere il problema. La ricerca di informazioni su ciò che potrebbe essere sbagliato non è risultata molto, ma questo post sembra indicare che almeno alcuni kernel Red Hat limitano un processo a 300 MB di memoria allocata per lo stack e a 10 MB per thread per lo stack, sembra che il problema potrebbe essere lì (anche se sembra strano e improbabile come bene).
Ho provato a cambiare la dimensione dello stack con " ulimit -s " per testarlo, ma qualsiasi valore diverso da 10240 e JVM non inizia con un errore di:
Error occurred during initialization of VM Cannot create VM thread. Out of system resources.
In genere posso aggirare Linux, ma in realtà non so molto sulla configurazione del sistema e non sono stato in grado di trovare nulla che affronti specificamente questo tipo di situazione. Qualsiasi idea su quale sistema o impostazione JVM potrebbe causare questo sarebbe apprezzata.
Modifiche : esecuzione del programma thread-limit menzionato da plinth , non si sono verificati errori fino a quando non ha provato a creare il 1529 ° thread.
Inoltre, il problema non si è verificato utilizzando una JVM 1.4 (si verifica con JVM 1.6.0_02 e 1.6.0_04, al momento non è possibile eseguire il test con una JVM 1.5).
Il codice per il thread test che sto usando è il seguente:
public class ThreadTest {
public static void main(String[] pArgs) throws Exception {
try {
// keep spawning new threads forever
while (true) {
new TestThread().start();
}
}
// when out of memory error is reached, print out the number of
// successful threads spawned and exit
catch ( OutOfMemoryError e ) {
System.out.println(TestThread.CREATE_COUNT);
System.exit(-1);
}
}
static class TestThread extends Thread {
private static int CREATE_COUNT = 0;
public TestThread() {
CREATE_COUNT++;
}
// make the thread wait for eternity after being spawned
public void run() {
try {
sleep(Integer.MAX_VALUE);
}
// even if there is an interruption, dont do anything
catch (InterruptedException e) {
}
}
}
}
Se lo esegui con una JVM 1.4, si bloccherà quando non può creare altri thread e richiede un kill -9 (almeno lo ha fatto per me).
Altre modifiche:
Si scopre che il sistema che sta riscontrando il problema utilizza il modello di threading LinuxThreads mentre un altro sistema che funziona correttamente utilizza il modello NPTL.
Soluzione 2
L'aggiornamento del kernel a una versione più recente (2.6.something) con thread NPTL ha risolto questo problema.
Altri suggerimenti
Hai esaminato questa risorsa ? Indica che dovresti essere in grado di eseguire thread-limit per trovare il numero massimo di thread e puoi modificarlo compilando glibc.
Questo è con Ubuntu Linux (1GB RAM)
dsm@localhost:~$ javac ThreadTest.java
dsm@localhost:~$ java ThreadTest
8113
dsm@localhost:~$ java -version
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)
dsm@localhost:~$
Puoi provarlo con JRockit JVM? IIRC, aveva un modello di threading diverso rispetto allo stock Sun JVM.
Le impostazioni in /etc/security/limits.d/90-nproc.conf
potrebbero sovrascrivere le impostazioni /etc/security/limits.conf
. Ciò può comportare che il sistema agisca in un modo diverso mostrato in ulimit -u
.