Come posso ottenere la traccia dello stack corrente in Java, come in .NET Environment.StackTrace
.
Ho trovato Thread.dumpStack()
ma non è quello che voglio: voglio recuperare la traccia dello stack, non stamparla.
Come posso ottenere la traccia dello stack corrente in Java, come in .NET Environment.StackTrace
.
Ho trovato Thread.dumpStack()
ma non è quello che voglio: voglio recuperare la traccia dello stack, non stamparla.
Risposte:
È possibile utilizzare Thread.currentThread().getStackTrace()
.
Ciò restituisce una matrice di StackTraceElement
s che rappresentano la traccia dello stack corrente di un programma.
String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e);
stackoverflow.com/a/10620951/11236
new Throwable().getStackTrace()
è molto più veloce, perché non ha bisogno di controllare this != Thread.currentThread()
e aggira i potenziali costi generali JVM di chiamarlo tramite classe figlio ( Exception extends Throwable
)
Thread.currentThread().getStackTrace();
va bene se non ti interessa quale sia il primo elemento dello stack.
new Throwable().getStackTrace();
avrà una posizione definita per il tuo metodo attuale, se questo è importante.
(new Throwable()).getStackTrace()
è anche più veloce (vedi bugs.sun.com/bugdatabase/view_bug.do?bug_id=6375302 )
(new Exception()).getStackTrace()
quando la traccia dello stack richiesta è sul thread corrente (che sarà sempre il caso diThread.currentThread().getStackTrace();
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
new Exception().printStackTrace(System.out)
cosa che posso ricordare, il ciclo for probabilmente ha meno overhead, ma dovresti comunque usarlo solo come cosa di debugging ...
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) { if(ste.toString().contains("mypackages")){ System.out.println(ste); } }
Thread.currentThread().getStackTrace();
è disponibile da JDK1.5.
Per una versione precedente, puoi reindirizzare exception.printStackTrace()
a StringWriter()
:
StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
new Throwable().getStackTrace()
è disponibile dal JDK 1,4 ...
Puoi usare i beni comuni di Apache per questo:
String fullStackTrace = org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);
org.apache.commons.lang3
, la linea completa è:org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);
org.apache.commons.lang3
, che inizialmente ho trascurato: l'importazione utilizza lang3
invece di lang
e sostituisce getFullStackTrace
con getStackTrace
.
ExceptionUtils.getStackTrace(new Throwable())
espressione per ottenere la traccia dello stack.
Su Android un modo molto più semplice è usare questo:
import android.util.Log;
String stackTrace = Log.getStackTraceString(exception);
Per ottenere la traccia dello stack di tutti i thread è possibile utilizzare l'utilità jstack, JConsole o inviare un segnale kill -quit (su un sistema operativo Posix).
Tuttavia, se si desidera farlo a livello di codice, è possibile provare a utilizzare ThreadMXBean:
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] infos = bean.dumpAllThreads(true, true);
for (ThreadInfo info : infos) {
StackTraceElement[] elems = info.getStackTrace();
// Print out elements, etc.
}
Come accennato, se vuoi solo la traccia dello stack del thread corrente è molto più semplice - Usa solo Thread.currentThread().getStackTrace()
;
System.err.println(elems[i])
su ciascuno). La seconda riga dello snippet è mancante bean.
prima dumpAllThreads
ma credo che la maggior parte delle persone possa risolverlo.
Un'altra soluzione (solo 35 31 caratteri):
new Exception().printStackTrace();
new Error().printStackTrace();
Tony, come commento alla risposta accettata, ha dato quella che sembra essere la migliore risposta che risponde effettivamente alla domanda del PO :
Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );
... l'OP NON ha chiesto come ottenere uno String
dalla traccia dello stack da un Exception
. E sebbene io sia un grande fan di Apache Commons, quando c'è qualcosa di così semplice come sopra non c'è alcun motivo logico per usare una libreria esterna.
Thread.getAllStackTraces()
che ti dà un Map<Thread, StackTraceElement[]>
. L'hotspot salva i punti ogni volta che deve salvarne uno. Zing può portare singoli thread in un punto di sicurezza senza disturbare l'altro. Ottenere uno stacktrace richiede un safepoint. Thread.getAllStackTraces()
ottiene tutte le tracce dello stack e arresta tutti i thread una sola volta. Certo, devi scoprire a quale mappatura sei effettivamente interessato.
Lo consiglio
Thread.dumpStack()
è un modo più semplice e ha il vantaggio di non creare effettivamente un'eccezione o gettabile quando potrebbe non esserci alcun problema ed è notevolmente più pertinente.
new Exception("Stack trace").printStackTrace();
quindi in realtà sta costruendo un Throwable
Ottenere stacktrace:
StackTraceElement[] ste = Thread.currentThread().getStackTrace();
Stack di stampa (JAVA 8+):
Arrays.asList(ste).forEach(System.out::println);
Stacktrage di stampa (JAVA 7):
StringBuilder sb = new StringBuilder();
for (StackTraceElement st : ste) {
sb.append(st.toString() + System.lineSeparator());
}
System.out.println(sb);
In Java 9 c'è un nuovo modo:
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 );
}
Ho un metodo di utilità che restituisce una stringa con stacktrace:
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();
}
E basta accedere come ...
...
catch (FileNotFoundException e) {
logger.config(getStackTrace(e));
}
java.util.logging.Logger#log(Level, String, Throwable)
lo fa già. Questo sta riscrivendo cose che già esistono nella libreria standard Java inutilmente e sta indirizzando i nuovi sviluppatori nella direzione sbagliata, che è lontano dalla documentazione. In questo modo ora hai costretto Stacktrace a essere formattato in un certo modo, dove l' logging
API ti consente di variare dinamicamente la formattazione dell'istruzione di registro mentre la specifichi. Per quanto ne sappia, log4j
ha anche un comportamento simile. Non reinventare la ruota perché finisci per perdere cose come ho spiegato.
Throwable
dalla Handler
s alla Formatter
s nel 2012 che era Java7, più di quanto ho elencato qui. E queste funzioni risalgono molto più a lungo di quanto Java7 sia stato in circolazione; quindi J2SE 5.0 javadocs)
try {
}
catch(Exception e) {
StackTraceElement[] traceElements = e.getStackTrace();
//...
}
o
Thread.currentThread().getStackTrace()
Forse potresti provare questo:
catch(Exception e)
{
StringWriter writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
e.printStackTrace(pw);
String errorDetail = writer.toString();
}
La stringa 'errorDetail' contiene lo stacktrace.
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
L'ultimo elemento dell'array rappresenta il fondo dello stack, che è l'invocazione del metodo meno recente nella sequenza.
A StackTraceElement has getClassName(), getFileName(), getLineNumber() and getMethodName().
scorrere in StackTraceElement e ottenere il risultato desiderato.
for (StackTraceElement ste : stackTraceElements )
{
//do your stuff here...
}
Ho usato le risposte dall'alto e ho aggiunto la formattazione
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);
}
}
È possibile utilizzare l'utilità jstack se si desidera controllare lo stack di chiamate corrente del processo.
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
Questo è un vecchio post, ma ecco la mia soluzione:
Thread.currentThread().dumpStack();
Maggiori informazioni e più metodi lì: http://javarevisited.blogspot.fr/2013/04/how-to-get-current-stack-trace-in-java-thread.html
Thread.dumpStack()
direttamente perché è un metodo statico.
System.out.println(Arrays.toString(Thread.currentThread().getStackTrace()));
Questo ti aiuterà a stampare la traccia dello stack senza loop.