2010-02-16 5 views
57

Ich erhalte diese Ausnahme in Java:Zu viele offene Dateien: wie viele offen sind, was sie sind, und wie viele kann die JVM offen

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

Ich bin für die Möglichkeiten suchen, diese zu beseitigen Problem.

Dieser Fehler weist offensichtlich darauf hin, dass JVM zu viele Handles zugewiesen hat, und das zugrunde liegende Betriebssystem wird es nicht mehr zulassen. Entweder lecke ich irgendwo mit nicht korrekt geschlossenen Verbindungen/Streams.

Dieser Prozess läuft für Tage non-stop und löst schließlich die Ausnahme aus. Es wiederholt sich nach 12-14 Tagen der Betriebszeit.

Wie bekämpft man das? Gibt es eine Möglichkeit, eine Liste der zugewiesenen Handles in JVM zu erhalten oder zu verfolgen, wenn ein bestimmter Wert erreicht wird? Ich würde gerne drucken lassen und sehen, wie es wächst und wann. Ich kann einen Profiler nicht verwenden, weil es ein Produktionssystem ist und Schwierigkeiten haben, es in der Entwicklung zu reproduzieren. Irgendein Vorschlag?

Ich überwache die freie Größe des Heapspeichers und hebe einen "Alarm" an, wenn er sich 1% des in -Xmx angegebenen Gesamtwerts nähert. Ich weiß auch, dass, wenn meine Thread-Anzahl über 500 steigt, etwas definitiv außer Kontrolle gerät. Nun, gibt es eine Möglichkeit zu wissen, dass meine JVM zu viele Griffe von OS zuweist und sie nicht zurück gibt, z. Steckdosen, geöffnete Dateien usw. Wenn ich das gewusst hätte, wüsste ich, wo und wann.

+1

Können Sie mehr bieten Informationen über JVM und OS? Außerdem schlage ich vor, dass Sie mehr Mühe darauf verwenden, dies in einer Entwicklungsumgebung zu reproduzieren. Es kann ein Aufwand sein, aber wenn Sie ein solches Problem haben, wird der Versuch, auf einem Produktionssystem zu beobachten und zu berichten, wahrscheinlich länger dauern. – Timothy

+1

Es passiert immer wieder auf Linux-Computern, die virtualisiert laufen, und wir haben keine Möglichkeit, dies zu reproduzieren, indem wir 2 Wochen schwere Tests durchführen. Ich habe das nicht auf Windows-Boxen passiert. Sie haben recht, am besten fangen Sie es in dev., Aber ich möchte auch einige Fähigkeiten in den Server selbst für die Selbstüberwachung für die Zukunft eingebettet haben. – Dima

+1

RE Ihre Bearbeitung. Ich glaube nicht, dass die JVM Ihnen sagen kann, wie sich Dateien geöffnet haben. Das ist vielleicht eine nette Funktion, die Sun hinzufügen kann, aber bis dahin müssen Sie einen externen Prozess verwenden, um es Ihnen zu sagen. Wenn Sie es wirklich in der JVM benötigen, schreiben Sie einen Code, der lsof ausführt und das Ergebnis zurückgibt. Zusätzlich kann das Limit von offenen Dateien geändert werden. Unter Linux können Sie beispielsweise die Datei /etc/security/limits.conf ändern. – bramp

Antwort

27

Sie sagen nicht, welches Betriebssystem Sie laufen lassen, aber wenn Sie auf Linux ausgeführt wird, können Sie den Befehl lsof

lsof -p <pid of jvm> 

verwenden, das alle Dateien von der JVM geöffnet auflistet. Oder wenn Sie unter Windows laufen, können Sie Process Explorer anzeigen, die alle geöffneten Dateien für alle Prozesse anzeigen.

Dadurch können Sie hoffentlich eingrenzen, welches Bit des Codes die Dateien geöffnet hält.

+0

Gute Idee. Überprüfen Sie die Markierungen, die Sie an "lsof" übergeben können, um alle X Sekunden zu wiederholen. – Timothy

+0

Ich habe den Kommentar zu Linixes hinzugefügt. Vielen Dank für den Hinweis! – Dima

+2

Ich würde gerne wissen, ob meine Lösung Ihnen geholfen hat, das Problem zu finden. Auch wenn es nicht vertraulich oder zu viel Mühe ist, könnten Sie am Ende erklären, was das Problem verursacht hat? – bramp

23

Da Sie unter Linux sind, würde ich vorschlagen, dass Sie das/proc-Dateisystem überprüfen. Innerhalb von proc finden Sie einen Ordner mit der PID Ihres Prozesses, der einen Ordner 'fd' enthält. Wenn Ihr Prozess-ID 1234 ist, ist der Weg

/proc/1234/fd 

In diesem Ordner werden, finden Sie Links zu allen geöffneten Dateien (do a 'ls -l'). Normalerweise können Sie anhand des Dateinamens feststellen, welche Bibliothek/Code geöffnet werden kann und nicht die Datei schließen.

+0

Danke, das ist nützlich, aber was ich brauche, ist etwas, das vermeiden wird, in ein Dateisystem oder OS zu graben. Ich möchte, dass der JVM-Prozess mir sagt, warum es "krank" ist, der Grund, warum ich es will, ist, den Benutzern die Kopfschmerzen zu ersparen, wenn etwas schief geht. – Dima

10

Sie können die Grenze der geöffneten Dateien ändern folgendes /etc/security/limits.conf durch Zusatz:

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

Dann Sie die Konfiguration neu zu laden können sysctl -p auf der Schale verwenden. Überprüfen Sie this article.

Nur der Vollständigkeit halber können Sie überprüfen, was für geöffnete Dateien die Strombegrenzung ist mit: ulimit -n

10

So vollständige Antwort (I kombiniert Antworten von @phisch und @bramp). Wenn Sie alle Prozesse überprüfen möchten, sollten Sie sudo verwenden. Es ist auch schön, das Ergebnis in einer Datei zu speichern - lsof ist nicht billig + diese Datei könnte für weitere Untersuchungen nützlich sein.

sudo lsof > lsof.log 

anzeigen Bösewichte:

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 

speichern Liste von Datei-Deskriptoren als auch in Datei:

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

zeigen nach oben offene Dateien:

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

Vielen Dank, wirklich nützlich! Ich glaube, du hast ein Stück im dritten Befehl vergessen: Es sollte 'sudo ls -l/proc/114970/fd> fd.log' sein. – ocramot

+0

@ocramot, bitte schön! p.s. Du hattest recht, ich habe meine Antwort korrigiert. – Jimilian