“Java.lang.OutOfMemoryError: no se puede crear un nuevo hilo nativo”

Estamos obteniendo "java.lang.OutOfMemoryError : unable to create new native Thread ” en 8GB RAM VM después de 32k threads (ps -eLF | grep -c java)

Sin embargo, "top" and "free -m" shows 50% free memory available . JDk es de 64 bits y probado tanto con HotSpot como con JRockit. El servidor tiene Linux 2.6.18

También probamos los límites del OS stack size (ulimit -s) y los límites máximos del proceso (ulimit -u), el aumento del limit.conf pero todo fue en vano.

También probamos casi todas las combinaciones posibles de tamaño de stack, manteniéndola baja, alta, etc.

El script que usamos para ejecutar la aplicación es

 /opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m -Xss128k -jar JavaNatSimulator.jar /opt/tools/jnatclients/natSimulator.properties 

Gracias por la respuesta.

Hemos intentado editar /etc/security/limits.conf y ulimit, pero sigue siendo el mismo

 [root@jboss02 ~]# ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 72192 max locked memory (kbytes, -l) 32 max memory size (kbytes, -m) unlimited open files (-n) 65535 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 10240 cpu time (seconds, -t) unlimited max user processes (-u) 72192 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 

Esto no es un problema de memoria, aunque el nombre de la excepción lo sugiere muy bien, pero es un problema de recursos del sistema operativo. Se está quedando sin hilos nativos, es decir, cuántos hilos el sistema operativo le permitirá usar su JVM.

Este es un problema poco común, porque rara vez se necesitan tantos. ¿Tienes un montón de hilos incondicionales en donde los hilos deberían pero no terminan?

Puede considerar volver a escribir usando Callable / Runnables bajo el control de un Executor si es posible. Hay muchos ejecutores estándar con varios comportamientos que su código puede controlar fácilmente.

(Hay muchas razones por las cuales el número de subprocesos es limitado, pero varían de sistema operativo a sistema operativo)

Es probable que su sistema operativo no permita la cantidad de subprocesos que intenta crear o que esté llegando a algún límite en la JVM. Especialmente si es un número redondo como 32k, un límite de un tipo u otro es un culpable muy probable.

¿Estás seguro de que realmente necesitas hilos de 32k? La mayoría de los lenguajes modernos tienen algún tipo de soporte para grupos de hilos reutilizables. Estoy seguro de que Java también tiene algo en su lugar (como ExecutorService , como mencionó el usuario Jesper). Tal vez podría solicitar subprocesos de dicho grupo, en lugar de crear nuevos manualmente.

Me encontré con el mismo problema durante la prueba de carga, la razón es porque JVM no puede crear un nuevo subproceso de Java más. A continuación está el código fuente de JVM

 if (native_thread->osthread() == NULL) { // No one should hold a reference to the 'native_thread'. delete native_thread; if (JvmtiExport::should_post_resource_exhausted()) { JvmtiExport::post_resource_exhausted( JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS, "unable to create new native thread"); } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "unable to create new native thread"); } Thread::start(native_thread);` 

Causa raíz: JVM lanza esta excepción cuando JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR (recursos agotados (significa memoria agotada)) o JVMTI_RESOURCE_EXHAUSTED_THREADS (hilos agotados).

En mi caso, Jboss está creando demasiados hilos para atender la solicitud, pero todos los hilos están bloqueados. Debido a esto, JVM también se agota con los hilos y la memoria (cada hilo retiene la memoria, que no se libera, porque cada hilo está bloqueado).

Analizado los volcados de hilos de java observados, casi 61K hilos están bloqueados por uno de nuestros métodos, lo que está causando este problema. A continuación se muestra la parte del volcado de subprocesos

 "SimpleAsyncTaskExecutor-16562" #38070 prio=5 os_prio=0 tid=0x00007f9985440000 nid=0x2ca6 waiting for monitor entry [0x00007f9d58c2d000] java.lang.Thread.State: BLOCKED (on object monitor) 

Yo recomendaría también mirar el Tamaño de stack de subprocesos y ver si se crean más subprocesos. El tamaño de stack de subprocesos predeterminado para JRockit 1.5 / 1.6 es de 1 MB para VM de 64 bits en el sistema operativo Linux. Los hilos de 32K requerirán una cantidad significativa de memoria física y virtual para cumplir este requisito.

Intente reducir el tamaño de la stack a 512 KB como punto de partida y vea si ayuda a crear más hilos para su aplicación. También recomiendo explorar el escalamiento horizontal, por ejemplo dividiendo el procesamiento de sus aplicaciones en más máquinas físicas o virtuales.

Cuando se utiliza una máquina virtual de 64 bits, el límite verdadero dependerá de la disponibilidad de la memoria física y virtual del sistema operativo y de los parámetros de ajuste del sistema operativo, como ulimitc. También recomiendo el siguiente artículo como referencia:

OutOfMemoryError: no se puede crear un nuevo hilo nativo – Problema Desmitificado

Tuve el mismo problema debido a procesos fantasmas que no aparecieron cuando usaba top in bash. Esto evitó que la JVM generara más hilos.

Para mí, se resolvió al listar todos los procesos java con jps (simplemente ejecuta jps en tu shell) y los eliminó por separado usando el comando kill -9 pid bash para cada proceso fantasma.

Esto podría ayudar en algunos escenarios.

Si su trabajo está fallando debido a OutOfMemmory en los nodos, puede cambiar el número de mapas máximos y reductores y la JVM opta por cada uno. mapred.child.java.opts (el valor predeterminado es 200Xmx) por lo general debe boostse en función del hardware específico de los nodos de datos.

Este enlace podría ser útil … ver por favor

su configuración de JBoss tiene algunos problemas, /opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m Xms y Xmx están limitando el uso de la memoria de JBoss, al valor configurado, así que desde el 8Gb usted tiene el servidor solo está usando 512M + algo extra para su propio propósito, aumente ese número, recuerde dejar algo gratis para el sistema operativo y otras cosas que se ejecutan allí y puede ser que lo ejecute a pesar del código desagradable. Reparar el código sería bueno también, si puedes.

Tiene la posibilidad de enfrentar el java.lang.OutOfMemoryError: Unable to create new native thread siempre que la JVM solicite un nuevo subproceso del sistema operativo. Siempre que el sistema operativo subyacente no pueda asignar un nuevo hilo nativo, se lanzará este OutOfMemoryError. El límite exacto para los hilos nativos es muy dependiente de la plataforma, por lo que se recomienda conocer esos límites ejecutando una prueba similar al ejemplo del enlace a continuación. Pero, en general, la situación que causa java.lang.OutOfMemoryError: Unable to create new native thread pasa por las siguientes fases:

  1. La aplicación que ejecuta dentro de JVM solicita un nuevo subproceso de Java
  2. El código nativo JVM proxies la solicitud para crear un nuevo hilo nativo para el sistema operativo El sistema operativo intenta crear un nuevo hilo nativo que requiere que la memoria se asigne a la secuencia
  3. El sistema operativo rechazará la asignación de memoria nativa porque el tamaño del proceso Java de 32 bits ha agotado su espacio de direcciones de memoria; por ejemplo, se ha alcanzado el límite de tamaño de proceso (2-4) GB o la memoria virtual del sistema operativo se ha agotado por completo
  4. Java.lang.OutOfMemoryError: no se puede crear un nuevo error de thread nativo.

Referencia: https://plumbr.eu/outofmemoryerror/unable-to-create-new-native-thread

Tuve este mismo problema y resultó ser un uso incorrecto de una API de Java. Estaba inicializando un constructor en un método de procesamiento por lotes que no se suponía que debía iniciarse más de una vez.

Básicamente, estaba haciendo algo como:

 for (batch in batches) { process_batch(batch) } def process_batch(batch) { var client = TransportClient.builder().build() client.processList(batch) } 

cuando debería haber hecho esto:

 for (batch in batches) { var client = TransportClient.builder().build() process_batch(batch, client) } def process_batch(batch, client) { client.processList(batch) } 

Para encontrar qué procesos están creando hilos, intente:

 ps huH 

Normalmente redirijo la salida a un archivo y analizo el archivo fuera de línea (el recuento de subprocesos para cada proceso es el esperado o no)

En primer lugar, no culparía tanto al OS / VM … sino al desarrollador que escribió el código que crea muchos hilos . Básicamente, en algún lugar de su código (o terceros) se crean muchos hilos sin control .

Revise cuidadosamente las stacktraces / código y controle la cantidad de subprocesos que se crean. Normalmente, su aplicación no debería necesitar una gran cantidad de subprocesos, si lo hace es un problema diferente.