web-dev-qa-db-fra.com

"Java.lang.OutOfMemoryError: impossible de créer un nouveau thread natif"

Nous obtenons "Java.lang.OutOfMemoryError : unable to create new native Thread "sur 8 Go RAM VM après 32k threads (ps -eLF | grep -c Java)

Cependant, "top" and "free -m" shows 50% free memory available. JDk est 64 bits et essayé avec HotSpot et JRockit.Server a Linux 2.6.18

Nous avons également essayé les limitations de OS stack size (ulimit -s) et du processus maximum (ulimit -u), l’augmentation de limite.conf mais en vain.

Nous avons également essayé presque toutes les combinaisons possibles de tailles de tas, en les maintenant bas, élevés, etc.

Le script que nous utilisons pour exécuter l'application est 

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

Merci pour la réponse.

Nous avons essayé d’éditer /etc/security/limits.conf et ulimit mais toujours la même chose

[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
104
Deepak Tewani

Ce n'est pas un problème de mémoire, même si le nom de l'exception le suggère fortement, mais un problème de ressources du système d'exploitation. Vous manquez de threads natifs, c'est-à-dire combien de threads le système d'exploitation autorisera votre machine virtuelle Java à utiliser. 

C'est un problème peu commun, car vous en avez rarement besoin. Avez-vous beaucoup de fils inconditionnels générés où les fils devraient mais ne finissent pas? 

Vous pourriez envisager de réécrire en utilisant Callable/Runnables sous le contrôle d'un exécuteur, si possible. Il existe de nombreux exécuteurs standard ayant divers comportements que votre code peut facilement contrôler.

(Le nombre de threads est limité pour plusieurs raisons, mais elles varient d'un système d'exploitation à l'autre)

J'ai rencontré le même problème lors du test de chargement, car JVM ne parvient pas à créer un nouveau thread Java. Ci-dessous le code source de la machine virtuelle Java 

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);`

Cause fondamentale: la machine virtuelle Java lève cette exception lorsque JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR (ressources épuisées (signifie mémoire Épuisé)) ou JVMTI_RESOURCE_EXHAUSTED_THREADS (thread épuisé).

Dans mon cas, Jboss crée trop de threads pour pouvoir répondre à la demande, mais tous les threads sont bloqués. De ce fait, la JVM utilise également des threads avec de la mémoire (chaque thread contient de la mémoire, qui n'est pas libérée car chaque thread est bloqué). 

L'analyse des vidages de threads Java a révélé que près de 61 000 threads sont bloqués par l'une de nos méthodes, ce qui est à l'origine de ce problème. Ci-dessous la partie de Thread Dump 

"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)
10
Madhu Cheepati

Il est probable que votre système d'exploitation n'autorise pas le nombre de threads que vous essayez de créer ou que vous atteignez une limite dans la JVM. Surtout s'il s'agit d'un nombre rond tel que 32k, une limite d'un type ou d'un autre est très probablement coupable.

Êtes-vous sûr d'avoir vraiment besoin de threads 32k? La plupart des langues modernes prennent en charge les groupes de threads réutilisables. Je suis sûr que Java dispose également d'un élément (par exemple, ExecutorService, comme l'a mentionné l'utilisateur Jesper). Vous pourriez peut-être demander des threads à partir d'un tel pool, au lieu d'en créer manuellement de nouveaux.

Je vous recommande de regarder également la taille de pile de threads et de voir si vous obtenez plus de threads créés. La taille de pile de threads par défaut pour JRockit 1.5/1.6 est de 1 Mo pour 64 bits VM sous Linux. Les threads 32K nécessiteront une quantité importante de mémoire physique et virtuelle pour satisfaire à cette exigence. 

Essayez de réduire la taille de la pile à 512 Ko comme point de départ et voyez si cela aide à créer plus de threads pour votre application. Je recommande également d'explorer la mise à l'échelle horizontale, par exemple. répartir le traitement de votre application sur plusieurs machines physiques ou virtuelles.

Lorsque vous utilisez une machine virtuelle 64 bits, la limite réelle dépend de la disponibilité de la mémoire virtuelle et physique du système d'exploitation et des paramètres de réglage du système d'exploitation, tels que ulimitc. Je recommande également l'article suivant comme référence:

OutOfMemoryError: impossible de créer un nouveau thread natif - Problème démystifié

5
P-H

J'ai eu le même problème en raison de processus fantômes qui n'apparaissaient pas lors de l'utilisation de top in bash. Cela a empêché la JVM de générer plus de threads.

Pour moi, le problème est résolu lors de la liste de tous les processus Java avec jps (il suffit d'exécuter jps dans votre shell) et de les tuer séparément à l'aide de la commande kill -9 pid bash pour chaque processus fantôme.

Cela pourrait aider dans certains scénarios.

3
mac7

Vous avez une chance de faire face au Java.lang.OutOfMemoryError: Unable to create new native thread chaque fois que la machine virtuelle demande un nouveau thread à partir du système d'exploitation. Chaque fois que le système d'exploitation sous-jacent ne peut pas allouer un nouveau thread natif, cette erreur OutOfMemoryError est renvoyée. La limite exacte pour les threads natifs est très dépendante de la plate-forme. Il est donc recommandé de connaître ces limites en exécutant un test similaire à l'exemple de lien ci-dessous. Mais, en général, la situation à l'origine de Java.lang.OutOfMemoryError: Unable to create new native thread passe par les phases suivantes:

  1. Un nouveau thread Java est demandé par une application s'exécutant dans la machine virtuelle
  2. Le code natif JVM envoie un proxy à la demande de création d'un nouveau thread Natif vers le système d'exploitation. Le système d'exploitation essaie de créer un nouveau thread natif qui nécessite que la mémoire soit allouée au thread 
  3. Le système d'exploitation refusera L'allocation de mémoire native, soit parce que la taille du processus Java 32 bits A épuisé son espace d'adressage mémoire - par exemple. (2-4) La taille du processus Limite a été atteinte - ou la mémoire virtuelle du système d'exploitation a été totalement épuisée
  4. L'erreur Java.lang.OutOfMemoryError: impossible de créer un nouveau thread Natif est générée.

Référence: https://plumbr.eu/outofmemoryerror/unable-to-create-new-native-thread

1

votre configuration JBoss a quelques problèmes, /opt/jrockit-jdk1.6/bin/Java -Xms512m -Xmx512m Xms et Xmx limitent votre utilisation de la mémoire JBoss, à la valeur configurée, donc à partir du 8Gb que vous avez le serveur n’utilise que 512M + de ressources supplémentaires à ses propres fins, augmentez ce nombre, rappelez-vous de laisser quelques-unes libres pour le système d’exploitation et les autres éléments qui y sont exécutés; il se peut que vous l’exécutiez en dépit du code peu recommandable . Sois gentil aussi, si tu peux.

1
user3390284

Si votre travail échoue à cause de OutOfMemmory sur les nœuds, vous pouvez modifier votre nombre maximal de cartes et de réducteurs et choisir la machine virtuelle pour chacun. mapred.child.Java.opts (la valeur par défaut est 200Xmx) doit généralement être augmenté en fonction du matériel spécifique de vos nœuds de données.

Ce lien pourrait être utile ... vérifier

1
Pavan Kumar K

J'ai eu le même problème et il s'est avéré que c'était une mauvaise utilisation d'une API Java. J'initialisais un générateur dans une méthode de traitement par lots qui n'était pas censée être initialisée plus d'une fois.

En gros, je faisais quelque chose comme:

for (batch in batches) {
    process_batch(batch)
}

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

quand j'aurais dû faire ceci:

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

def process_batch(batch, client) {
    client.processList(batch)
}
0
anthonybell

Si jvm est démarré via systemd, il se peut qu'il y ait une limite maxTasks par processus (tâches, en réalité, threads) dans certains systèmes d'exploitation Linux.

Vous pouvez vérifier cela en exécutant "état du service" et vérifier s'il existe une limite maxTasks. Si c'est le cas, vous pouvez le supprimer en modifiant /etc/systemd/system.conf, en ajoutant une configuration: DefaultTasksMax = infinity

0
Clement.Xu

Cette erreur peut faire surface pour deux raisons:

  • Il n'y a pas de place dans la mémoire pour accueillir de nouveaux threads.

  • Le nombre de threads dépasse la limite du système d'exploitation.

Je doute que le nombre de threads a dépassé la limite du processus Java

Il est donc probable que le problème soit dû à la mémoire. Un point à considérer est: 

les threads ne sont pas créés dans le segment de mémoire de la machine virtuelle Java. Ils sont créés à l'extérieur le tas JVM. Donc, s'il reste moins de place dans la RAM, après la JVM allocation de tas, l'application se heurtera à “Java.lang.OutOfMemoryError: impossible de créer un nouveau thread natif”.

La solution possible consiste à réduire la mémoire de tas ou à augmenter la taille globale du ram 

0
Maverick

Pour trouver quels processus créent des threads, essayez:

ps huH

Je redirige normalement la sortie vers un fichier et analyse le fichier hors connexion (le nombre de threads pour chaque processus est comme prévu ou non) 

0
user8521771