18 votes

Java : Impossible de créer un nouveau thread natif

J'ai une application Java qui est hébergée par une société d'hébergement web. Tous les quelques jours, mon application tombe en panne avec :

[2011-03-09 15:52:14,501] ERROR http-12021-9 
java.lang.OutOfMemoryError: unable to create new native thread
    at java.lang.Thread.start0(Native Method)
    at java.lang.Thread.start(Thread.java:597)

L'hébergeur dit que cela signifie que mon application perd de la mémoire, mais les outils que j'ai montrent que la mémoire libre est toujours disponible. Comme l'erreur crée toujours un nouveau thread natif, je pense que le problème se situe au niveau de la configuration de la JVM et des ressources du système d'exploitation.

Comment puis-je empêcher cette erreur de se produire ?

10voto

jatal Points 118

Il est possible que vous ayez atteint votre limite d'utilisateurs pour le nombre de fichiers ouverts.

Je crois que chaque processus/thread consomme un ou plusieurs descripteurs de fichiers.

Par exemple, lorsque cela se produit pour votre utilisateur, la commande shell "no" fonctionnera, car les commandes shell forkent un processus à exécuter (vous voyez des erreurs comme "-bash : fork : retry : Resource temporarily unavailable")

J'ai rencontré ce problème et j'ai constaté que seul l'utilisateur actuel était incapable de générer des procs... les autres utilisateurs n'étaient pas affectés.

Pour résoudre ce problème, augmentez votre paramètre ulimit -n (nombre maximum de fichiers ouverts)... les détails suivent.

Vous pouvez voir vos limites d'utilisateur avec la commande :

ulimit -a

Augmentez votre limite maximale de fichiers avec ce qui suit :

ulimit -n 65536 

Voici ce que j'ai en ce moment :

$ 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) 256797
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 75000
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) 100000
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Pour voir toutes les limites explicites de votre système :

cat /etc/security/limits.conf

Remarque : j'utilise Oracle Linux 6.3 - les résultats peuvent varier légèrement d'une distribution à l'autre.

7voto

Tayyab Points 2337

Il s'agit probablement d'un problème de JVM au niveau du serveur web. Veuillez consulter le lien suivant pour plus de détails,

http://blog.egilh.com/2006/06/2811aspx.html

2voto

Brian Roach Points 43787

Lorsque vous lancez votre processus, la JVM dispose d'une taille de tas limitée (128 Mo par défaut). Ce serveur peut très bien avoir plus de mémoire, mais pas votre JVM - vous avez tout utilisé.

Vous pouvez changer cela avec l'option -Xms y -Xmx mais je suggère de trouver la fuite de mémoire d'abord :)

2voto

Sunchezz Points 623

Cette réponse s'adresse à tous ceux qui exécutent java via systemd. (par exemple, un service tomcat créé par eux-mêmes).

Je faisais tourner mon application java sur le serveur via Tomcat. J'ai également créé une unité de service dans systemd pour plus de commodité, afin qu'elle démarre au démarrage du serveur et que je puisse également la contrôler via systemd (ou service tomcat restart ).

Mais il existe certaines valeurs par défaut pour les unités systemd et leurs tâches (threads) maximales autorisées. Pour moi, sur ma machine, c'était 195 Tâches. Une fois que j'ai changé la valeur dans l'unité de service avec TasksMax=1024 et l'a rechargé avec systemctl daemon-reload tout a fonctionné comme prévu.

Par exemple, le fichier des unités de service dans /etc/systemd/system/tomcat.service

[Unit]
Description=Tomcat9
After=network.target

[Service]
Type=forking
User=tomcat9
Group=tomcat9

TasksMax=1048

Environment=CATALINA_PID=/opt/tomcat/tomcat9.pid
Environment=JAVA_HOME=/usr/lib/jvm/default-java
Environment=CATALINA_HOME=/opt/tomcat
Environment=CATALINA_BASE=/opt/tomcat
Environment="CATALINA_OPTS=-Xms2048m -Xmx28384m"
Environment="JAVA_OPTS=-Dfile.encoding=UTF-8 -Dnet.sf.ehcache.skipUpdateCheck=true -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC"

ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh

[Install]
WantedBy=multi-user.target

1voto

Edwin Buck Points 33097

Avez-vous fait des recherches sur la mémoire ? Lancez jconsole et observez ou enregistrez votre consommation de mémoire sur une période de 24 heures. Si elle augmente (en moyenne) sans redescendre, c'est que vous manquez de mémoire et que vous n'en avez peut-être pas assez pour stocker les détails de votre nouveau fil.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X