2010-02-16 8 views
57

JVM Je reçois cette exception en Java:Trop de fichiers ouverts: combien sont ouverts, ce qu'ils sont, et combien peuvent l'ouvrir

java.io.FileNotFoundException: (Too many open files) 

Je cherche les moyens d'éliminer cette problème.

Cette erreur indique clairement que JVM a alloué trop de handles et que le système d'exploitation sous-jacent ne lui en laissera pas plus. Soit j'ai une fuite quelque part avec des connexions/flux mal fermés.

Ce processus s'exécute pendant des jours non-stop et lève finalement l'exception. Il arrive à plusieurs reprises après 12-14 jours de temps de fonctionnement.

Comment combattez-vous cela? Existe-t-il un moyen d'obtenir une liste des poignées allouées dans la JVM ou la piste quand elle atteint un certain montant? J'aimerais les faire imprimer et voir comment ça grandit et quand. Je ne peux pas utiliser un profileur parce que c'est un système de production et qu'il est difficile de le reproduire en développement. Toute suggestion? Je surveille la taille du tas libre et déclenche une "alarme" quand elle approche 1% du total spécifié en -Xmx. Je sais aussi que si le nombre de threads dépasse 500, alors quelque chose ne va plus. Maintenant, est-il un moyen de savoir que mon JVM alloue trop de poignées de OS et ne les rend pas, par exemple. des sockets, des fichiers ouverts, etc. Si j'avais su cela, je saurais où chercher et quand.

+1

Pouvez-vous fournir plus des informations sur la JVM et l'OS? Aussi, je suggère que vous fassiez plus d'efforts pour reproduire ceci dans un environnement de développement. Cela peut être compliqué, mais lorsque vous rencontrez un tel problème, essayer d'observer et de signaler un système de production prend plus de temps. – Timothy

+1

Cela arrive souvent sur des Linux qui sont virtualisés et nous n'avons pas vraiment l'option de reproduire ceci en exécutant 2 semaines de tests lourds. Je n'ai pas vu cela se produire sur les boîtes de fenêtres cependant. Vous avez raison, il est préférable de l'attraper en développement, mais je voudrais aussi avoir une certaine capacité intégrée dans le serveur lui-même pour l'auto-surveillance pour l'avenir. – Dima

+1

RE votre modification. Je ne pense pas que la JVM puisse vous dire comment les fichiers ont été ouverts. Cela pourrait être une fonctionnalité intéressante pour Sun, mais d'ici là, vous devrez utiliser un processus externe pour vous le dire. Si vous en avez vraiment besoin dans la JVM, écrivez du code qui exécute lsof et renvoie le résultat. En outre, la limite des fichiers ouverts peut être modifiée. Par exemple, sous Linux, vous pouvez modifier le fichier /etc/security/limits.conf. – bramp

Répondre

27

Vous n'avez pas dit quel système d'exploitation que vous utilisez, mais si vous utilisez Linux, vous pouvez utiliser la commande lsof

lsof -p <pid of jvm> 

qui listera tous les fichiers ouverts par la machine virtuelle Java. Ou si vous exécutez sur Windows, vous pouvez Process Explorer qui affichera tous les fichiers ouverts pour tous les processus.

Cela permettra, espérons-le, d'affiner le bit du code qui garde les fichiers ouverts.

+0

Bonne idée. Vérifiez les drapeaux que vous pouvez passer à 'lsof' pour répéter toutes les X secondes. – Timothy

+0

J'ai ajouté le commentaire à propos de Linixes., Merci pour l'astuce lsof! – Dima

+2

Je serais intéressé de savoir si ma solution vous a aidé à dépister le problème. Aussi, si ce n'est pas confidentiel ou trop de tracas pourriez-vous expliquer ce qui a causé le problème à la fin? – bramp

23

Puisque vous êtes sous Linux, je vous suggère de vérifier le/proc-Filesystem. Dans proc, vous trouverez un dossier avec le PID de votre processus contenant un dossier appelé 'fd'. Si votre ID de processus est 1234, le chemin est être

/proc/1234/fd 

Dans ce dossier, vous trouverez des liens vers tous les fichiers ouverts (faire un « ls -l »). Habituellement, vous pouvez dire par le nom de fichier quelle bibliothèque/code pourrait ouvrir et ne pas fermer le fichier.

+0

Merci, cela est utile, mais ce que je suis après est quelque chose qui va éviter de creuser dans un système de fichiers ou un système d'exploitation. Je veux que le processus de la JVM me dise pourquoi il est "malade", la raison pour laquelle je veux que ce soit pour épargner aux utilisateurs le mal de tête, c'est que quelque chose ne va pas. – Dima

10

Vous pouvez modifier la limite des fichiers ouverts en ajoutant ce qui suit à /etc/security/limits.conf:

* soft nofile 2048 # Set the limit according to your needs 
* hard nofile 2048 

Ensuite, vous pouvez recharger la configuration à l'aide sysctl -p sur la coque. Vérifiez this article.

Juste pour être complet, vous pouvez vérifier ce qui est la limite actuelle pour les fichiers ouverts via: ulimit -n

10

Alors, réponse complète (je combine les réponses de @phisch et @bramp). Si vous souhaitez vérifier tous les processus, vous devez utiliser sudo. Aussi, il est bon d'enregistrer le résultat dans le fichier - lsof n'est pas bon marché + ce fichier pourrait être utile pour une étude plus approfondie.

sudo lsof > lsof.log 

Voir les méchants:

cat lsof.log | awk '{ print $2 " " $1; }' | sort -rn | uniq -c | sort -rn | head -5 

    2687 114970 java 
    131 127992 nginx 
    109 128005 nginx 
    105 127994 nginx 
    103 128019 nginx 

Enregistrer liste des descripteurs de fichier à fichier ainsi:

sudo ls -l /proc/114970/fd > fd.log 

Montrer les fichiers ouverts:

cat fd | awk '{ print $11 }' | sort -rn | uniq -c | sort -rn | head -n20 
+2

Merci beaucoup, vraiment utile! Je pense que vous avez oublié un morceau dans la troisième commande, cependant: il devrait être 'sudo ls -l/proc/114970/fd> fd.log' – ocramot

+0

@ocramot, vous êtes les bienvenus! p.s. tu avais raison, j'ai réparé ma réponse. – Jimilian

Questions connexes