Как получить текущую трассировку стека в Java, например, как в .NET вы можете сделать Environment.StackTrace
?
Я нашел, Thread.dumpStack()
но это не то, что я хочу - я хочу вернуть трассировку стека, а не распечатать его.
Как получить текущую трассировку стека в Java, например, как в .NET вы можете сделать Environment.StackTrace
?
Я нашел, Thread.dumpStack()
но это не то, что я хочу - я хочу вернуть трассировку стека, а не распечатать его.
Ответы:
Вы можете использовать Thread.currentThread().getStackTrace()
.
Это возвращает массив StackTraceElement
s, которые представляют текущую трассировку стека программы.
new Throwable().getStackTrace()
гораздо быстрее, потому что не нужно проверять this != Thread.currentThread()
и обходить потенциальные издержки JVM при вызове через child-class ( Exception extends Throwable
)
Thread.currentThread().getStackTrace();
хорошо, если вам все равно, какой первый элемент стека.
new Throwable().getStackTrace();
будет иметь определенную позицию для вашего текущего метода, если это имеет значение.
(new Throwable()).getStackTrace()
выполняется быстрее (см. bugs.sun.com/bugdatabase/view_bug.do?bug_id=6375302 )
(new Exception()).getStackTrace()
когда запрашиваемая трассировки стека на текущем потоке (который всегда будет иметь место в случаеThread.currentThread().getStackTrace();
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
new Exception().printStackTrace(System.out)
что я помню, цикл for, вероятно, имеет меньше накладных расходов, но вы все равно должны использовать это только как средство отладки ...
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) { if(ste.toString().contains("mypackages")){ System.out.println(ste); } }
Thread.currentThread().getStackTrace();
доступен с JDK1.5.
Для более старой версии вы можете перенаправить exception.printStackTrace()
на StringWriter()
:
StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
new Throwable().getStackTrace()
доступен с JDK1.4…
Вы можете использовать Apache для этого:
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
, который я изначально пропустил - импорт использует lang3
вместо lang
, а заменяет getFullStackTrace
на getStackTrace
.
ExceptionUtils.getStackTrace(new Throwable())
выражение для получения трассировки стека.
На Android гораздо проще использовать это:
import android.util.Log;
String stackTrace = Log.getStackTraceString(exception);
Чтобы получить трассировку стека всех потоков, вы можете использовать утилиту jstack, JConsole или отправить сигнал kill -quit (в операционной системе Posix).
Однако, если вы хотите сделать это программно, вы можете попробовать использовать ThreadMXBean:
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] infos = bean.dumpAllThreads(true, true);
for (ThreadInfo info : infos) {
StackTraceElement[] elems = info.getStackTrace();
// Print out elements, etc.
}
Как уже упоминалось, если вам нужна только трассировка стека текущего потока, это намного проще - просто используйте Thread.currentThread().getStackTrace()
;
System.err.println(elems[i])
для каждого). Вторая строка во фрагменте отсутствует bean.
раньше, dumpAllThreads
но я думаю, что большинство людей могли бы решить это.
Другое решение (всего 35 31 символов):
new Exception().printStackTrace();
new Error().printStackTrace();
Тони, в качестве комментария к принятому ответу, дал лучший ответ, который на самом деле отвечает на вопрос ОП :
Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );
... OP НЕ спрашивал, как получить String
трассировку стека от Exception
. И хотя я большой поклонник Apache Commons, когда есть что-то простое, как указано выше, нет логической причины использовать стороннюю библиотеку.
Thread.getAllStackTraces()
который дает вам Map<Thread, StackTraceElement[]>
. Hotspot будет защищать все потоки всякий раз, когда это необходимо. Zing может привести отдельные темы в безопасную точку, не мешая другим. Получение трассировки стека требует безопасной точки. Thread.getAllStackTraces()
получает все трассировки стека и останавливает все потоки только один раз. Конечно, вы должны выяснить, какое отображение вам на самом деле интересно.
Я предполагаю, что
Thread.dumpStack()
это более простой способ, и его преимущество заключается в том, что на самом деле не создается исключение и не может быть выброшено, когда проблемы могут вообще не быть, и это значительно более важно.
new Exception("Stack trace").printStackTrace();
так что он на самом деле строит Throwable
Получение трассировки стека:
StackTraceElement[] ste = Thread.currentThread().getStackTrace();
Печать трассировки стека (JAVA 8+):
Arrays.asList(ste).forEach(System.out::println);
Печатание укладки (JAVA 7):
StringBuilder sb = new StringBuilder();
for (StackTraceElement st : ste) {
sb.append(st.toString() + System.lineSeparator());
}
System.out.println(sb);
В Java 9 появился новый способ:
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 );
}
У меня есть служебный метод, который возвращает строку с трассировкой стека:
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();
}
И просто логит как ...
...
catch (FileNotFoundException e) {
logger.config(getStackTrace(e));
}
java.util.logging.Logger#log(Level, String, Throwable)
уже делает это. Это переписывает вещи, которые уже существуют в стандартной библиотеке Java без необходимости, и указывает новым разработчикам в неправильном направлении, что далеко от документации. Сделав это сейчас, вы заставили Stacktrace форматироваться определенным образом, где logging
API позволяет динамически изменять форматирование оператора log по мере его указания. Насколько мне известно, log4j
также имеет аналогичное поведение. Не изобретайте велосипед, потому что вы теряете вещи, как я объяснил.
Throwable
прочь к Handler
с помощью к Formatter
с в 2012 году , который был Java7, больше , чем я перечислил здесь И эти функции датируются гораздо дольше , чем Java7 было вокруг,. , следовательно , J2SE 5,0 JavaDocs)
try {
}
catch(Exception e) {
StackTraceElement[] traceElements = e.getStackTrace();
//...
}
или
Thread.currentThread().getStackTrace()
Может быть, вы могли бы попробовать это:
catch(Exception e)
{
StringWriter writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
e.printStackTrace(pw);
String errorDetail = writer.toString();
}
Строка errorDetail содержит трассировку стека.
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
Последний элемент массива представляет нижнюю часть стека, что является наименее недавним вызовом метода в последовательности.
A StackTraceElement has getClassName(), getFileName(), getLineNumber() and getMethodName().
переберите StackTraceElement и получите желаемый результат.
for (StackTraceElement ste : stackTraceElements )
{
//do your stuff here...
}
Я использовал ответы сверху и добавил форматирование
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);
}
}
Вы можете использовать утилиту jstack, если хотите проверить текущий стек вызовов вашего процесса.
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
Это старый пост, но вот мое решение:
Thread.currentThread().dumpStack();
Больше информации и методов здесь: http://javarevisited.blogspot.fr/2013/04/how-to-get-current-stack-trace-in-java-thread.html
Thread.dumpStack()
напрямую, потому что это статический метод.
System.out.println(Arrays.toString(Thread.currentThread().getStackTrace()));
Это поможет вам распечатать трассировку стека без цикла.