Ich denke darüber nach, ein Debug-Tool für meine Java-Anwendung zu erstellen.
Ich frage mich, ob es möglich ist, eine Stapelverfolgung zu erhalten, genau wie Exception.printStackTrace()
, ohne tatsächlich eine Ausnahme auszulösen.
Mein Ziel ist es, in einer bestimmten Methode einen Stapel zu sichern, um zu sehen, wer der Methodenaufrufer ist.
public static void dumpStack() { new Exception("Stack trace").printStackTrace(); }
stderr
, was die Implikation der Frage zu sein scheint.Wenn Sie die Ablaufverfolgung nur für den aktuellen Thread wünschen (und nicht für alle Threads im System, wie es Ram vorgeschlagen hat), gehen Sie wie folgt vor:
Thread.currentThread ().getStackTrace ()
Um den Anrufer zu finden, gehen Sie wie folgt vor:
Rufen Sie diese Methode innerhalb der Methode auf, die wissen muss, wer ihr Aufrufer ist. Ein Wort der Warnung: Der Index des aufrufenden Frames in der Liste kann je nach JVM variieren! Es hängt alles davon ab, wie viele Ebenen von Aufrufen sich in getStackTrace befinden, bevor Sie den Punkt erreichen, an dem die Ablaufverfolgung generiert wird. Eine robustere Lösung wäre, den Trace abzurufen und ihn zu durchlaufen, um nach dem Frame für getCallingMethodName zu suchen, und dann zwei Schritte weiter nach oben zu gehen, um den wahren Aufrufer zu finden.
quelle
Sie können eine Stapelverfolgung wie folgt erhalten:
Wenn Sie auf den Frame zugreifen möchten, können Sie mit t.getStackTrace () ein Array von Stack-Frames abrufen.
Beachten Sie, dass bei diesem Stacktrace (genau wie bei jedem anderen) möglicherweise einige Frames fehlen, wenn der Hotspot-Compiler mit der Optimierung beschäftigt war.
quelle
t.printStackTrace
mitt.printStackTrace(System.out)
.new Throwable().printStackTrace(System.out);
log.log(Level.SEVERE, "Failed to do something", new Throwable());
Beachten Sie, dass Thread.dumpStack () tatsächlich eine Ausnahme auslöst:
quelle
Sie können auch ein Signal an die JVM senden, um Thread.getAllStackTraces () auf einem laufenden Java-Prozess auszuführen, indem Sie ein QUIT-Signal an den Prozess senden.
Unter Unix / Linux verwenden Sie:
kill -QUIT process_id
Dabei ist process_id die Prozessnummer Ihres Java-Programms.Unter Windows können Sie in der Anwendung Strg-Pause drücken, obwohl dies normalerweise nur angezeigt wird, wenn Sie einen Konsolenprozess ausführen.
JDK6 hat eine weitere Option eingeführt, den Befehl jstack, mit dem der Stapel von jedem laufenden JDK6-Prozess auf Ihrem Computer angezeigt wird:
jstack [-l] <pid>
Diese Optionen sind sehr nützlich für Anwendungen, die in einer Produktionsumgebung ausgeführt werden und nicht einfach geändert werden können. Sie sind besonders nützlich für die Diagnose von Laufzeit-Deadlocks oder Leistungsproblemen.
http://java.sun.com/developer/technicalArticles/Programming/Stacktrace/ http://java.sun.com/javase/6/docs/technotes/tools/share/jstack.html
quelle
Wenn Sie eine Capture-Ausgabe benötigen
quelle
Java 9 führte die
StackWalker
und unterstützenden Klassen zum Gehen des Stapels ein.Hier einige Ausschnitte aus dem Javadoc:
quelle
HPROF Java Profiler
Sie müssen dies nicht einmal im Code tun. Sie können Java HPROF an Ihren Prozess anhängen und jederzeit Control- \ drücken, um einen Heap-Dump auszugeben, Threads auszuführen usw. . . ohne Ihren Anwendungscode durcheinander zu bringen. Dies ist etwas veraltet, Java 6 wird mit der GUI-Jconsole geliefert, aber ich finde HPROF immer noch sehr nützlich.
quelle
Die Antwort von Rob Di Marco ist bei weitem die beste, wenn Sie gerne etwas ausgeben
stderr
.Wenn Sie in a
String
mit neuen Zeilen gemäß einer normalen Ablaufverfolgung erfassen möchten , können Sie Folgendes tun:quelle