Wie kann man ein Java-Programm verfolgen?

25

Als Systemadministrator sehe ich mich manchmal Situationen gegenüber, in denen sich ein Programm abnormal verhält und dabei überhaupt keine Fehler oder unsinnige Fehlermeldungen erzeugt.

In der Vergangenheit - bevor Java eintraf - gab es zwei Gegenmaßnahmen:

  1. Wenn nichts anderes hilft - RTFM ;-)
  2. Wenn auch nur 1. nicht hilft - verfolgen Sie die Systemaufrufe und sehen Sie, was passiert

Ich benutze normalerweise strace -ffür diese Aufgabe mit Linux (andere Betriebssysteme haben ähnliche Trace-Tools). Nun, während dies normalerweise für jedes altmodische Programm gut funktioniert, wird die Ablaufverfolgung sehr unscharf, wenn dasselbe auf einem Java- Prozess ausgeführt wird. Es gibt so viele Systemaufrufe, die scheinbar nichts mit einer echten Aktion zu tun haben, dass es schrecklich ist, einen solchen Dump zu durchsuchen.

Gibt es dafür bessere Möglichkeiten (wenn der Quellcode nicht verfügbar ist)?

Nils
quelle

Antworten:

16

Wie bereits erwähnt, jstackist es großartig, weil es den vollständigen Stack-Trace aller aktiven Threads in der JVM liefert. Dasselbe kann mit SIGQUIT auf stderr der JVM abgerufen werden.

Ein weiteres nützliches Tool ist, jmapdas mithilfe der PID des Prozesses einen Heap-Dump aus dem JVM-Prozess abrufen kann:

jmap -dump:file=/tmp/heap.hprof $PID

Dieser Heap-Dump kann in Tools wie visualvm(die jetzt Teil der Standard-Java-SDK-Installation von Oracle mit dem Namen jvisualvm sind) geladen werden. Darüber hinaus kann VisualVM eine Verbindung zur laufenden JVM herstellen und Informationen zur JVM anzeigen, darunter Diagramme zur internen CPU-Auslastung, zur Thread-Anzahl und zur Heap-Auslastung - ideal, um Lecks aufzuspüren.

Ein anderes Tool jstatkann Garbage Collection-Statistiken für die JVM über einen Zeitraum erfassen, ähnlich wie vmstat, wenn es mit einem numerischen Argument ausgeführt wird (z. B.vmstat 3 . ) ausgeführt wird.

Schließlich ist es möglich, einen Java-Agenten zu verwenden, um die Instrumentierung aller Methoden aller Objekte zur Ladezeit zu übertragen. Die Bibliothek javassistkann dabei helfen, dies sehr einfach zu machen. Es ist also möglich, eine eigene Ablaufverfolgung hinzuzufügen. Das Schwierige dabei wäre, einen Weg zu finden, um die Trace-Ausgabe nur dann zu erhalten, wenn Sie es wollten, und nicht die ganze Zeit, was die JVM wahrscheinlich zu einem Crawl verlangsamen würde. Es gibt ein Programm, dtracedas so funktioniert. Ich habe es versucht, war aber nicht sehr erfolgreich. Beachten Sie, dass Agenten nicht alle Klassen instrumentieren können, da diejenigen, die zum Bootstrap der JVM erforderlich sind, geladen werden, bevor der Agent instrumentieren kann. Dann ist es zu spät, diesen Klassen Instrumentation hinzuzufügen.

Mein Vorschlag - Beginnen Sie mit VisualVM und prüfen Sie, ob dies die wichtigsten Informationen enthält, da die aktuellen Threads und wichtigen Statistiken für die JVM angezeigt werden können.

Asche
quelle
Übrigens, das ist eine großartige Frage. Ich hoffe, dass mehr Leute Antworten mit anderen Ideen hinzufügen. Als ich Leute, die jahrelang mit Java gearbeitet haben, nach dem Aufspüren gefragt habe, gaben sie mir leere Blicke. Vielleicht kennen sie die Beeindruckung von Strace einfach nicht.
Asche
10

Ebenso wenig können Sie beim Debuggen von fehlerhaften Programmen auf einem Linux-System ähnliche Tools zum Debuggen von JVMs auf Ihrem System verwenden.

Tool Nr. 1 - jvmtop

Ähnlich topkönnen Sie mit jvmtop feststellen , welche Klassen in den ausgeführten JVMs auf Ihrem System aktiv sind. Nach der Installation rufen Sie es folgendermaßen auf:

$ jvmtop.sh

Die Ausgabe sieht ähnlich aus wie das Werkzeug top:

 JvmTop 0.8.0 alpha   amd64  8 cpus, Linux 2.6.32-27, load avg 0.12
 http://code.google.com/p/jvmtop

  PID MAIN-CLASS      HPCUR HPMAX NHCUR NHMAX    CPU     GC    VM USERNAME   #T DL
 3370 rapperSimpleApp  165m  455m  109m  176m  0.12%  0.00% S6U37 web        21
11272 ver.resin.Resin [ERROR: Could not attach to VM]
27338 WatchdogManager   11m   28m   23m  130m  0.00%  0.00% S6U37 web        31
19187 m.jvmtop.JvmTop   20m 3544m   13m  130m  0.93%  0.47% S6U37 web        20
16733 artup.Bootstrap  159m  455m  166m  304m  0.12%  0.00% S6U37 web        46

Tool Nr. 2 - jvmmonitor

Eine andere Alternative ist die Verwendung von jvmmonitor . JVM Monitor ist ein in Eclipse integrierter Java-Profiler zur Überwachung von CPU, Threads und Speichernutzung von Java-Anwendungen. Sie können damit entweder automatisch laufende JVMs auf dem Localhost finden oder über einen Port @ Host eine Verbindung zu Remote-JVMs herstellen.

ss von jvmmonitor

Tool # 3 - Visualisierung

VisualVM ist wahrscheinlich "das Werkzeug", um Probleme mit der JVM zu beheben . Der Funktionsumfang ist ziemlich umfangreich, und Sie können einen sehr detaillierten Einblick in die Innereien erhalten.

Profilieren Sie die Anwendungsleistung oder analysieren Sie die Speicherzuordnung:

ss von visualvm # 2

Thread-Dumps nehmen und anzeigen:

ss von visualvm # 3

Verweise

slm
quelle
2

Wenn Sie RHEL OpenJDK verwenden (oder ähnliches, der Punkt ist, dass es nicht Oracle's JDK ist), können Sie dafür SystemTap verwenden .

Einige Sonden werden aktiviert , indem Java - Befehlszeilenoptionen -XX:+DTraceMethodProbes, -XX:+DTraceAllocProbes, -XX:+DTraceMonitorProbes. Beachten Sie, dass das Aktivieren dieser Tests die Programmleistung erheblich beeinträchtigt.

Hier ist ein Beispiel für ein SystemTap-Skript:

#!/usr/bin/stap

probe hotspot.class_loaded {
    printf("%12s [???] %s\n", name, class);
}

probe hotspot.method_entry, 
      hotspot.method_return {
    printf("%12s [%3d] %s.%s\n", name, thread_id, class, method);
}

probe hotspot.thread_start, 
      hotspot.thread_stop {
    printf("%12s [%3d] %s\n", name, id, thread_name);
}

probe hotspot.monitor_contended_enter, 
      hotspot.monitor_contended_exit {
    printf("%12s [%3d] %s\n", name, thread_id, class);
}

Sie können auch verwenden jstack(), um den Java-Stapel des Prozesses abzurufen . Dies funktioniert jedoch nur, wenn Sie SystemTap vor JVM starten .


Beachten Sie, dass SystemTap jede Methode verfolgt. Es ist auch nicht in der Lage, die Argumente der Methode abzurufen. Eine weitere Option ist die Verwendung von JVM-eigenen Tracing-Funktionen, die als JVMTI bezeichnet werden. Eine der bekanntesten JVMTI-Implementierungen ist BTrace .

myaut
quelle
0

Es wird empfohlen, Jackplay auszuprobieren , ein JVM-Tracing-Tool, mit dem Sie Methodenein- und -ausgänge nachverfolgen können , ohne den Code zu ändern oder erneut bereitzustellen.

alfredx
quelle
Sie können es nicht an eine laufende JVM anhängen. Abgesehen davon - interessantes Tool
Nils