Wie erhalte ich den aktuellen Stack-Trace in Java, wie in .NET Environment.StackTrace
?
Ich habe gefunden, Thread.dumpStack()
aber es ist nicht das, was ich will - ich möchte den Stack-Trace zurückbekommen, nicht ausdrucken.
Wie erhalte ich den aktuellen Stack-Trace in Java, wie in .NET Environment.StackTrace
?
Ich habe gefunden, Thread.dumpStack()
aber es ist nicht das, was ich will - ich möchte den Stack-Trace zurückbekommen, nicht ausdrucken.
Antworten:
Sie können verwenden Thread.currentThread().getStackTrace()
.
Das gibt ein Array von StackTraceElement
s zurück, das den aktuellen Stack-Trace eines Programms darstellt.
String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e);
Einzeiler,
new Throwable().getStackTrace()
ist viel schneller, weil es this != Thread.currentThread()
potenzielle JVM-Overheads beim Aufrufen über child-class ( Exception extends Throwable
) nicht überprüfen und umgehen muss
Thread.currentThread().getStackTrace();
ist in Ordnung, wenn es Ihnen egal ist, was das erste Element des Stapels ist.
new Throwable().getStackTrace();
wird eine definierte Position für Ihre aktuelle Methode haben, wenn das wichtig ist.
(new Throwable()).getStackTrace()
ist auch schneller auszuführen (siehe bugs.sun.com/bugdatabase/view_bug.do?bug_id=6375302 )
(new Exception()).getStackTrace()
der angeforderte Stack-Trace im aktuellen Thread befindet (was fürThread.currentThread().getStackTrace();
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
new Exception().printStackTrace(System.out)
Ich kann mich erinnern, dass die for-Schleife wahrscheinlich weniger Overhead hat, aber Sie sollten diese sowieso nur als Debugging-Sache verwenden ...
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) { if(ste.toString().contains("mypackages")){ System.out.println(ste); } }
Thread.currentThread().getStackTrace();
ist seit JDK1.5 verfügbar.
Bei einer älteren Version können Sie exception.printStackTrace()
zu einem umleiten StringWriter()
:
StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
new Throwable().getStackTrace()
ist seit JDK1.4 verfügbar…
Sie können Apaches Commons dafür verwenden:
String fullStackTrace = org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);
org.apache.commons.lang3
org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);
org.apache.commons.lang3
, den ich anfangs übersehen habe - der Import verwendet lang3
anstelle von lang
und ersetzt getFullStackTrace
durch getStackTrace
.
ExceptionUtils.getStackTrace(new Throwable())
Ausdruck zum Abrufen des Stack-Trace zu verwenden.
Unter Android ist es weitaus einfacher, Folgendes zu verwenden:
import android.util.Log;
String stackTrace = Log.getStackTraceString(exception);
Um die Stapelverfolgung aller Threads abzurufen, können Sie entweder das Dienstprogramm jstack, JConsole, verwenden oder ein Kill-Quit-Signal senden (auf einem Posix-Betriebssystem).
Wenn Sie dies jedoch programmgesteuert ausführen möchten, können Sie ThreadMXBean verwenden:
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] infos = bean.dumpAllThreads(true, true);
for (ThreadInfo info : infos) {
StackTraceElement[] elems = info.getStackTrace();
// Print out elements, etc.
}
Wie bereits erwähnt, ist es viel einfacher, wenn Sie nur den Stack-Trace des aktuellen Threads verwenden möchten Thread.currentThread().getStackTrace()
.
System.err.println(elems[i])
jeweils tun ). Die zweite Zeile im Snippet fehlt bean.
vor dem, dumpAllThreads
aber ich denke, die meisten Leute könnten das klären.
Eine andere Lösung (nur 35 31 Zeichen):
new Exception().printStackTrace();
new Error().printStackTrace();
Tony hat als Kommentar zu der akzeptierten Antwort die scheinbar beste Antwort gegeben, die die Frage des OP tatsächlich beantwortet :
Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );
... das OP hat NICHT gefragt, wie man eine String
vom Stack-Trace von einem bekommt Exception
. Und obwohl ich ein großer Fan von Apache Commons bin, gibt es keinen logischen Grund, eine externe Bibliothek zu verwenden, wenn es etwas so Einfaches wie das oben Genannte gibt.
Thread.getAllStackTraces()
, was Ihnen eine gibt Map<Thread, StackTraceElement[]>
. Hotspot speichert alle Threads sicher, wann immer sie einen sicheren Punkt benötigen. Zing kann einzelne Threads zu einem sicheren Punkt bringen, ohne den anderen zu stören. Um eine Stapelverfolgung zu erhalten, ist ein Sicherheitspunkt erforderlich. Thread.getAllStackTraces()
Ruft alle Stack-Traces ab und stoppt alle Threads nur einmal. Natürlich müssen Sie herausfinden, an welchem Mapping Sie tatsächlich interessiert sind.
Ich schlage vor, dass
Thread.dumpStack()
ist ein einfacher Weg und hat den Vorteil, dass keine Ausnahme erstellt oder ausgelöst werden kann, wenn möglicherweise überhaupt kein Problem vorliegt, und ist wesentlich wichtiger.
new Exception("Stack trace").printStackTrace();
Es wird also tatsächlich ein Throwable
Stacktrace erhalten:
StackTraceElement[] ste = Thread.currentThread().getStackTrace();
Stacktrace drucken (JAVA 8+):
Arrays.asList(ste).forEach(System.out::println);
Stacktrage drucken (JAVA 7):
StringBuilder sb = new StringBuilder();
for (StackTraceElement st : ste) {
sb.append(st.toString() + System.lineSeparator());
}
System.out.println(sb);
In Java 9 gibt es einen neuen Weg:
public static void showTrace() {
List<StackFrame> frames =
StackWalker.getInstance( Option.RETAIN_CLASS_REFERENCE )
.walk( stream -> stream.collect( Collectors.toList() ) );
for ( StackFrame stackFrame : frames )
System.out.println( stackFrame );
}
Ich habe eine Dienstprogrammmethode, die einen String mit dem Stacktrace zurückgibt:
static String getStackTrace(Throwable t) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
t.printStackTrace(pw);
pw.flush();
sw.flush();
return sw.toString();
}
Und loggen Sie einfach wie ...
...
catch (FileNotFoundException e) {
logger.config(getStackTrace(e));
}
java.util.logging.Logger#log(Level, String, Throwable)
macht das schon. Dies schreibt Dinge, die bereits in der Java-Standardbibliothek vorhanden sind, unnötig um und weist neue Entwickler in die falsche Richtung, die von der Dokumentation abweicht. Auf diese Weise haben Sie jetzt die Formatierung des Stacktrace auf eine bestimmte Weise erzwungen, wobei Sie mit der logging
API die Formatierung der Protokollanweisung dynamisch variieren können, während Sie sie angeben. Meines Wissens hat log4j
auch ähnliches Verhalten. Erfinden Sie das Rad nicht neu, weil Sie am Ende Dinge verlieren, wie ich sie erklärt habe.
Throwable
das Handler
s an das s bis zum Formatter
s im Jahr 2012 weitergeben, das Java7 war, mehr als ich hier aufgelistet habe. Und diese Funktionen reichen viel länger zurück als Java7; daher J2SE 5.0 javadocs)
try {
}
catch(Exception e) {
StackTraceElement[] traceElements = e.getStackTrace();
//...
}
oder
Thread.currentThread().getStackTrace()
Vielleicht könnten Sie das versuchen:
catch(Exception e)
{
StringWriter writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
e.printStackTrace(pw);
String errorDetail = writer.toString();
}
Die Zeichenfolge 'errorDetail' enthält die Stapelverfolgung.
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
Das letzte Element des Arrays stellt den unteren Rand des Stapels dar. Dies ist der am wenigsten aktuelle Methodenaufruf in der Sequenz.
A StackTraceElement has getClassName(), getFileName(), getLineNumber() and getMethodName().
Durchlaufen Sie StackTraceElement und erhalten Sie das gewünschte Ergebnis.
for (StackTraceElement ste : stackTraceElements )
{
//do your stuff here...
}
Ich habe Antworten von oben verwendet und Formatierungen hinzugefügt
public final class DebugUtil {
private static final String SEPARATOR = "\n";
private DebugUtil() {
}
public static String formatStackTrace(StackTraceElement[] stackTrace) {
StringBuilder buffer = new StringBuilder();
for (StackTraceElement element : stackTrace) {
buffer.append(element).append(SEPARATOR);
}
return buffer.toString();
}
public static String formatCurrentStacktrace() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
return formatStackTrace(stackTrace);
}
}
Sie können das Dienstprogramm jstack verwenden, wenn Sie den aktuellen Aufrufstapel Ihres Prozesses überprüfen möchten.
Usage:
jstack [-l] <pid>
(to connect to running process)
jstack -F [-m] [-l] <pid>
(to connect to a hung process)
jstack [-m] [-l] <executable> <core>
(to connect to a core file)
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
(to connect to a remote debug server)
Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message
Dies ist ein alter Beitrag, aber hier ist meine Lösung:
Thread.currentThread().dumpStack();
Weitere Informationen und Methoden finden Sie dort: http://javarevisited.blogspot.fr/2013/04/how-to-get-current-stack-trace-in-java-thread.html
Thread.dumpStack()
wegen seiner statischen Methode direkt aufrufen .
System.out.println(Arrays.toString(Thread.currentThread().getStackTrace()));
Auf diese Weise können Sie die Stapelverfolgung ohne Schleife drucken.