Límite bajo de subprocesos de proceso único de Java en Red Hat Linux
Pregunta
Tengo un problema en una máquina de prueba que ejecuta Red Hat Linux (la versión del kernel es 2.4.21-37.ELsmp) usando Java 1.6 (1.6.0_02 o 1.6.0_04).El problema es que, una vez que se crea una cierta cantidad de subprocesos en un solo grupo de subprocesos, el sistema operativo no quiere o no puede crear más.
Esto parece ser específico de la creación de subprocesos en Java, ya que el programa de límite de subprocesos de C pudo crear aproximadamente 1,5k subprocesos.Además, esto no sucede con una JVM Java 1.4...puede crear más de 1,4k subprocesos, aunque obviamente se manejan de manera diferente con respecto al sistema operativo.
En este caso, la cantidad de hilos que corta es de apenas 29 hilos.Esto se puede comprobar con un programa Java simple que simplemente crea subprocesos hasta que recibe un error y luego imprime la cantidad de subprocesos que creó.El error es un
java.lang.OutOfMemoryError: unable to create new native thread
Esto parece no verse afectado por cosas como la cantidad de subprocesos utilizados por otros procesos o usuarios o la cantidad total de memoria que el sistema está utilizando en ese momento.Las configuraciones de JVM como Xms, Xmx y Xss tampoco parecen cambiar nada (lo cual es de esperar, considerando que el problema parece estar relacionado con la creación de subprocesos del sistema operativo nativo).
La salida de "ulimit -a" es la siguiente:
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
El límite de procesos de usuario no parece ser el problema.La búsqueda de información sobre lo que podría estar mal no ha dado muchos resultados, pero esta publicación parece indicar que al menos algunos núcleos de Red Hat limitan un proceso a 300 MB de memoria asignada para la pila, y a 10 MB por subproceso para la pila, parece que el problema podría estar ahí (aunque también parece extraño e improbable).
Intenté cambiar el tamaño de la pila con "ulimit -s" para probar esto, pero cualquier valor que no sea 10240 y la JVM no comienza con un error de:
Error occurred during initialization of VM Cannot create VM thread. Out of system resources.
Generalmente puedo manejar Linux, pero realmente no sé mucho sobre la configuración del sistema y no he podido encontrar nada que aborde específicamente este tipo de situación.Se agradecería cualquier idea sobre qué sistema o configuración de JVM podría estar causando esto.
Ediciones:Ejecutando el programa de límite de subprocesos mencionado por pedestal, no hubo ningún error hasta que intentó crear el hilo 1529.
El problema tampoco ocurrió al usar una JVM 1.4 (ocurre con las JVM 1.6.0_02 y 1.6.0_04, no se puede probar con una JVM 1.5 en este momento).
El código para la prueba de hilo que estoy usando es el siguiente:
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) {
}
}
}
}
Si ejecuta esto con una JVM 1.4, se bloqueará cuando no pueda crear más subprocesos y requiera un kill -9 (al menos así fue para mí).
Más edición:
Resulta que el sistema que tiene el problema usa el modelo de subprocesos LinuxThreads, mientras que otro sistema que funciona bien usa el modelo NPTL.
Solución 2
La actualización del kernel a una versión más nueva (2.6.algo) con subprocesos NPTL solucionó este problema.
Otros consejos
¿Has mirado este recurso?Indica que debería poder ejecutar thread-limit para encontrar el número máximo de subprocesos y modificarlo compilando glibc.
Esto es con Ubuntu Linux (1 GB de 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:~$
¿Puedes probarlo con JRockit JVM?IIRC, tenía un modelo de subprocesos diferente al de Sun JVM original.
Los ajustes en /etc/security/limits.d/90-nproc.conf
puede estar anulando su /etc/security/limits.conf
ajustes.Eso puede hacer que el sistema actúe de una manera diferente a la que se muestra en ulimit -u
.