Lange Rede, kurzer Sinn: Einige Mitarbeiter betreiben ein ziemlich altes Setup (oc4j jdk1.5.6 in x86_64) mit einer Anwendung, die geschäftskritisch ist. Sie haben kürzlich versucht, eine neue Version der Anwendung zu implementieren, aber sobald sie dies tun, werfen die Java-Prozesse einen Core-Dump und sterben.
Das Problem ist, die Core Dumps scheinen in Ordnung zu sein, gdb kann sie öffnen, aber jmap und andere Tools weigern sich, sie zu verarbeiten:
%Vor%Und neuere Versionen werfen eine Ausnahme:
%Vor%gdb bietet wenig Informationen ohne Symbole:
%Vor%Die einzigen wertvollen Informationen, die ich aus dem Kern gesammelt habe, sind die meisten Threads sind blockiert (ich bin weit davon entfernt, ein gdb-Guru zu sein):
%Vor%Außerdem weiß ich nicht, ob es wirklich relevant ist. Die App ist fast immer schwer geladen, und meine Wette ist, dass es schon einige Sperrkonflikte gab, aber da es eine andere Team-App ist, ist mein Wissen darüber ziemlich oberflächlich.
Ich denke, das ist eine lange Geschichte, aber gibt es etwas, was wir tun können, um einen Java-Thread-Dump oder so etwas zu bekommen? Hat Sun Debuginfo der jdk angeboten, wie ich denke, ist jetzt mit openjdk verfügbar?
Vielen Dank im Voraus.
UPDATE: Das andere Team hat das Problem gelöst, ohne Informationen aus dem Core-Dump zu erhalten, nur durch Versuch und Irrtum nach der erfolgreichen Replizierung des Problems in einem Testsystem. Ich bin immer noch fasziniert über die Sache: Wie man einen alten Java-Core-Dump debuggt, den Jmap nicht verarbeiten kann, könnte es wertvolle Informationen für die Zukunft sein, obwohl es scheint, dass es keine Lösung für dieses Problem gibt. Wahrscheinlich wurde der JVM-Speicher beschädigt und deshalb kann jmap ihn nicht verarbeiten.
Sie können beim Starten der Anwendung die folgende JVM-Option hinzufügen, mit der Sie bei einem schwerwiegenden JVM-Fehler einen beliebigen Befehl ausführen können:
%Vor%Sie könnten beispielsweise einen Befehl (oder ein Skript) ausführen, der bestimmte Aktionen ausführt, wie zum Beispiel einen Heap- oder Thread-Dump.
Jmap und andere JVM-Dienstprogramme sind extrem versionsabhängig. Von Ihrem Fehler ist es selbsterklärend, dass hoffentlich das gleiche jvm in Ihrem Fall nicht verwendet wird.
Java VisualVM kann Core Dumps direkt laden. Aber Sie müssen das gleiche jvm verwenden, das die Kerndatei erstellt hat.
Ressourcenverknüpfung:
kjkoster hat hier eine Lösung in diesem Tutorial gefunden.
Sie müssen die Jmap verwenden, die mit der JVM geliefert wird. Von deinem Fehler Nachricht Ich nehme an, dass Sie eine andere Version von jmap als verwenden der JVM.
Überprüfen Sie, welche JVMs auf Ihrem Computer installiert sind, und stellen Sie sicher, dass sie installiert sind Wenn Sie Jmap ausführen, verwenden Sie die richtige Version.
Um solche Probleme zu lösen, verlasse ich mich nie auf den Pfad. Stattdessen setze ich JAVA_HOME auf sei diejenige, die die JVM verwendet und dann sowohl die JVM als auch die jmap aufruft so:
Code:
%Vor%Hoffe, das hilft.
Es ist eine vollständige Lösung Schritt für Schritt von Chamilad gegeben. Ich hoffe, es wird Ihre Ursache und Lösungsprozedur klären.
Fast jeder Java-Entwickler kennt jmap- und jstack-Tools komm mit dem JDK. Diese bieten Funktionen zum Extrahieren von Heap- und Thread-Informationen einer laufenden JVM-Instanz. Einfach.
Was passiert, wenn es eine laufende JVM gibt, die einen Deadlock verursacht hat und Sie einen Thread-Dump ausführen wollen, während der Prozess läuft? Du gehst hinein und führst Folgendes aus.
%Vor%Stellt sich heraus, dass das System nicht weiß, welcher Jstack ist. Du machst keine Panik, aber du bekommst ein kleines Gefühl im Hinterkopf und sagst, dass du diesen Freitag nicht früh verlässt.
Was passiert ist, ist, dass die laufende JVM auf einer JRE und nicht auf einem JDK basiert. Die JRE ist eine minimale Laufzeit, die die Überwachungs- und Analysetools, die das JDK packt, nicht packt.
Was sind unsere Möglichkeiten hier?
Funktionen wie jstack sind in der Datei tools.jar implementiert, die in <JDK_HOME>/lib
Ordner gepackt ist. Wir können dies verwenden, um die JStack
-Klasse aufzurufen und einen Thread-Dump des laufenden Prozesses zu erhalten.
So marschieren wir weiter, um das JDK herunterzuladen und zu extrahieren und dann folgendes auszuführen:
%Vor%.. und den folgenden Fehler finden.
%Vor%Verdammt! Wieder verwöhnt!
Wie lösen wir das? Der obige Fehler tritt auf, wenn der Prozess libattach.so
file nicht finden kann, das mit der Funktion Dynamic Attach für JStack
zusammenhängt. Wenn die folgende Umgebungsvariable gesetzt wird, kann die JVM den libattach.so
Datei.
Lassen Sie uns nun JStack erneut ausführen, diesmal mit Ergebnissen!
%Vor%Jetzt, da wir den Thread-Dump haben, gehen wir weiter zum Heap-Dump. Das Werkzeug, das wir normalerweise verwenden, ist jmap, aber das ist auch nicht auf der JRE verfügbar. Na und? Wir können die Binärdatei im bin Verzeichnis des JDK verwenden, richtig? richtig?
%Vor%Nein! Wenn Sie die JDK-Version nicht mit der exakten Version der JRE vergleichen, erhalten Sie das obige Problem (was ziemlich selbsterklärend ist). Also laden wir das JDK der JRE von oben herunter, unser Prozess läuft und führt jmap erneut aus.
%Vor%jmap hilft Ihnen nicht beim Debuggen eines Core Dumps. Die JVM löscht den Kern, wenn entweder ein Fehler vorliegt oder wenn Sie einen JNI-Code mit einem Problem haben. Organisationen mit unternehmenskritischen Anwendungen sollten leider ein Upgrade von nicht unterstützten Versionen der JVM als geschäftskritisch betrachten oder bereit sein, Oracle ein Vermögen für Hilfe zu zahlen.