Methode zum Finden eines Speicherlecks in großen Java-Heap-Dumps
Brauche ich ein memory-leak in einer Java-Anwendung. Ich habe einige Erfahrung mit dieser, möchte aber Rat auf eine Methode/Strategie. Jeder Verweis und Rat ist willkommen.
Über unsere situation:
- Heap-dumps sind größer als 1 GB
- Wir haben heap-dumps von 5 Anlässen.
- Wir haben keine test-Fall zu provozieren. Es passiert nur in den (massiven) - system test-Umgebung nach mindestens einer Woche Nutzung.
- Das system basiert auf einem intern entwickelten legacy-framework mit so vielen designfehlern, dass man Sie nicht alle aufzählen.
- Niemand versteht die Rahmen in die Tiefe. Es wurde übertragen auf eine Kerl in Indien, die kaum Schritt hält mit der Beantwortung von e-mails.
- Wir getan haben, snapshot-heap-dumps im Laufe der Zeit, und festgestellt, dass es nicht eine einzelne Komponente, die mit der Zeit immer größer. Es ist alles, was langsam wächst.
- Die oben genannten Punkte, der uns in die Richtung, dass es die Rahmenbedingungen homegrown ORM-system, das erhöht seinen Verbrauch, ohne Grenzen. (Dieses system bildet die Objekte in Dateien?! Also nicht wirklich ein ORM)
Frage: Was ist die Methode, dass half Sie erfolgreich mit der Jagd nach Lecks in einer enterprise-scale-Anwendung?
InformationsquelleAutor der Frage Rickard von Essen | 2010-03-24
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist fast unmöglich, ohne irgendein Verständnis von dem zugrunde liegenden code. Wenn Sie verstehen, die zugrunde liegenden code, dann kann man besser Sortieren, den Weizen von der Spreu von den Zillionen von bits von Informationen, die Sie bekommen in Ihre heap-dumps.
Können, können Sie auch nicht wissen, ob etwas ein Leck oder nicht, ohne zu wissen, warum das Klasse ist es in den ersten Platz.
Ich verbrachte die letzten paar Wochen tut genau dies, und ich habe ein iterativer Prozess.
Erste, ich fand die heap-Profiler im Grunde nutzlos. Sie können nicht analysieren, die enorme Haufen effizient.
Eher, verließ ich mich fast ausschließlich auf jmap Histogramme.
Ich kann mir vorstellen, du bist vertraut mit diesen, aber für diejenigen, die nicht:
erstellt ein Histogramm der live-heap. Kurz gesagt, es sagt Ihnen, die Namen der Klassen und wie viele Instanzen der einzelnen Klassen im heap.
Ich war dumping aus heap regelmäßig, alle 5 Minuten, 24h am Tag. Das mag wohl sein, zu präzise für Sie, aber das wesentliche ist die gleiche.
Lief ich mehrere verschiedene Analysen auf diesen Daten.
Schrieb ich ein Skript, um zwei Histogramme und dump, den Unterschied zwischen Ihnen. Also, wenn java.lang.String 10 war in der ersten dump, und 15 in der zweiten, mein script würde ausspucken "5 java.lang.String" sage mir, es ging bis um 5. Wenn es war untergegangen, die Zahl wäre negativ.
Ich würde einige dieser Unterschiede, Streifen Sie heraus alle Klassen, ging von Lauf zu Lauf, und nehmen Sie eine union mit dem Ergebnis. Am Ende, würde ich eine Liste der Klassen, die kontinuierlich wuchs über einen bestimmten Zeitraum. Offensichtlich sind diese Hauptkandidaten für undichte Klassen.
Jedoch, einige Klassen haben einige erhalten, während andere GC würde. Diese Klassen könnten leicht rauf und runter in der Gesamtwertung, aber immer noch undicht. So, könnten Sie fallen aus der "immer steigende" - Kategorie von Klassen.
Diese zu finden, habe ich konvertiert die Daten in einer Zeit-Serie und lud Sie in eine Datenbank, Postgres-spezifisch. Postgres ist praktisch, denn es bietet statistische Aggregatfunktionenso können Sie tun, einfache linear regression analysis auf die Daten, und finden Sie Klassen, die den trend, auch wenn Sie nicht immer an der Spitze der charts. Ich benutzte die regr_slope Funktion, auf der Suche nach Klassen mit einer positiven Steigung.
Ich fand diesen Prozess sehr erfolgreich und sehr effizient. Die Histogramme Dateien sind nicht wahnsinnig groß, und es war einfach laden Sie Sie von den Gastgebern. Sie waren nicht super teuer ist auf die Produktion system (zwingen Sie eine große GC, und blockieren die VM ein bisschen). Ich war dieses laufen auf einem system mit einem 2G-Java-heap.
Nun, all dies tun können, ist identifizieren Sie potenziell undichte Klassen.
Dies ist, wo das Verständnis, wie die Klassen verwendet werden, und ob Sie sollte oder sollte nicht Ihre kommt ins Spiel.
Zum Beispiel, können Sie feststellen, dass Sie eine Menge von Anzeigen.Eintrag Klassen, oder einige andere system-Klasse.
Es sei denn, du bist einfach Zwischenspeichern String, Tatsache ist, dass diese system-Klassen, während vielleicht die "Täter", nicht das "problem". Wenn Sie die Zwischenspeicherung einige application-Klasse, DIE Klasse ist ein besserer Indikator, wo dein problem liegt. Wenn Sie nicht cache-com.app.yourbean, dann wirst du nicht die zugehörige Karte.Eintrag gebunden.
Haben Sie einige Klassen, können Sie beginnen, durchsucht die code-Basis suchen, Instanzen und Referenzen. Da haben Sie Ihre eigenen ORM-layer (für gut oder schlecht), kann man wenigstens leicht, den Quellcode anzusehen. Wenn Sie ORM ist caching-Zeug, es ist wahrscheinlich ein caching-ORM-Klassen Verpackung Ihrer Anwendung Klassen.
Schließlich noch eine weitere Sache, die Sie tun können, ist, sobald Sie wissen, die Klassen, können Sie beginnen, eine lokale Instanz des Servers mit einem viel kleineren heap und kleinere dataset, und mit einer der die Profiler dagegen.
In diesem Fall können Sie tun, unit test, der betrifft nur 1 (oder wenige) der Dinge, die Sie denken können lecken. Sie könnten zum Beispiel starten Sie den server, führen Sie ein Histogramm, eine einzelne Aktion durchzuführen, und führen Sie das Histogramm wieder. Sie leckt Klasse sollte um 1 erhöht (oder was auch immer Ihre Einheit der Arbeit ist).
Profiler kann in der Lage sein, um Ihnen zu helfen verfolgen Sie den Besitzer, "jetzt durchgesickert" sind Klasse.
Aber, im Ende, sind Sie gehen zu müssen, haben ein gewisses Verständnis für Ihre code-Basis, um besser zu verstehen, was ist ein Leck, und was nicht, und warum ein Objekt in dem heap überhaupt, noch viel weniger, warum kann es sein, beibehalten wird wie ein Leck in Ihrem heap.
InformationsquelleAutor der Antwort Will Hartung
Werfen Sie einen Blick auf Eclipse Memory Analyzer. Es ist ein tolles tool (und sich selbst enthalten, nicht verlangen, Eclipse selbst installiert) 1) öffnen bis sehr großen Haufen sehr schnell und 2) hat einige Recht gute automatische Erkennungs-tools. Letzteres ist nicht perfekt, aber EMA bietet viele wirklich schöne Wege zum navigieren und Abfragen der Objekte im dump zu finden, alle möglichen undichten stellen.
Ich habe es in der Vergangenheit zu helfen, die Jagd nach verdächtigen Lecks.
InformationsquelleAutor der Antwort matt b
Diese Antwort baut auf @-Hartung. Ich bewarb mich um gleiche Verfahren zum diagnostizieren einer meiner memory-leaks und dachte, dass das teilen der details sparen würde, anderen Menschen Zeit.
Die Idee ist, postgres 'plot' Zeit vs. Speicher-Auslastung der einzelnen Klasse, zeichnen Sie eine Linie, fasst das Wachstum und die Objekte identifizieren, die am schnellsten wachsen:
Konvertieren heap dumps (brauchen mehrere) in einem format, das bequem ist für die Nutzung von postgres aus der heap-dump-format:
In eine csv-Datei mit den datetime-jeder heap-dump:
Verwenden Sie dieses Skript:
Erstellen Sie eine Tabelle, um die Daten in
Kopieren Sie die Daten in die neue Tabelle
Laufen die slop-Abfrage gegen die Dateigröße (Anzahl der bytes) Abfrage:
Interpretieren Sie die Ergebnisse:
Den Hang hinzugefügten bytes pro Sekunde (da die Einheit der Epoche wird in Sekunden angegeben). Wenn Sie mit Instanzen statt Größe, dann ist die Anzahl der Instanzen Hinzugefügt pro Sekunde.
Meine die Zeilen von code erstellen dieser joe.schmoe.BusinessObject war verantwortlich für das Speicher-Leck. Es war Sie das Objekt erstellen, anfügen an ein array ohne zu prüfen, ob es das schon gibt. Die anderen Objekte wurden auch erstellt, zusammen mit den BusinessObject in der Nähe der undichten code.
InformationsquelleAutor der Antwort joseph
Können Sie die Zeit beschleunigen? also kann man schreiben einer dummy-test-client, der Sie zwingt, es zu tun eine Woche im Wert von Ausschreibungen/Anfragen etc. in ein paar Minuten oder Stunden? Diese sind dein größter Freund und wenn Sie keine haben - schreiben.
Wir verwendet Netbeans eine Weile her, um zu analysieren, heap-dumps. Es kann ein bisschen langsam, aber es war effektiv. Eclipse gerade abgestürzt und die 32-bit-Windows-tools Tat, wie gut.
Wenn Sie Zugriff auf ein 64bit-system oder ein Linux-system mit 3GB oder mehr werden Sie finden es einfacher, zu analysieren, heap-dumps.
Haben Sie Zugang zu ändern, Protokolle und Berichte über Zwischenfälle? Große Unternehmen verfügen in der Regel über change-management und incident-management-teams, und dies kann hilfreich in aufspüren, wenn die Probleme begannen.
Wann begann es schief geht? Mit Leuten reden und versuchen, einige der Geschichte. Kann man jemand sagen: "Ja, es war, nachdem Sie die Fehler behoben in patch XYZ 6.43, dass wir komische Sachen passiert".
InformationsquelleAutor der Antwort Fortyrunner
Hatte ich Erfolg mit IBM Heap Analyzer. Es bietet verschiedene Ansichten des heap, einschließlich der größte drop-off in die Größe des Objekts, die am häufigsten vorkommenden Objekte, und die Objekte nach Größe sortiert.
InformationsquelleAutor der Antwort Drew Johnson
Wenn es passiert nach eine Woche Nutzung, und Ihre Anwendung wird als byzantinischer wie Sie es beschreiben, vielleicht sind Sie besser dran, Neustart jede Woche ?
Ich weiß es nicht, das problem zu lösen, aber es kann eine Zeit-effektive Lösung. Gibt es Zeit-Fenster, wenn Sie können, haben Ausfälle ? Können Sie Lastenausgleich-und Failover-einer Instanz, während der zweite ? Vielleicht können Sie veranlassen, ein starten, wenn der Speicher Verbrauch Verstöße gegen eine bestimmte Grenze (vielleicht auch monitoring per JMX oder ähnliches).
InformationsquelleAutor der Antwort Brian Agnew
Ich verwendet habe,jhatdas ist ein bisschen hart, aber es hängt von der Art des Rahmens, die Sie hatten.
InformationsquelleAutor der Antwort LB40