2009-07-01 4 views
809

Как получить текущую трассировку стека в Java, например, как в .NET вы можете сделать Environment.StackTrace?Получить текущую трассировку стека в Java

BTW, Thread.dumpStack() не то, что я хочу - я хочу получить обратно stack trace, а не распечатать его.

+65

Я ВСЕГДА использовать «новый Exception(). PrintStackTrace()» как выражение часы, когда я отладки в Eclipse. Это удобно, когда вы приостанавливаетесь в точке останова и хотите знать, откуда вы пришли. –

+20

@ TimBüthe: разве Eclipse уже не говорит вам о трассировке стека, когда вы находитесь в режиме отладки? Я думаю так. –

+34

Arrays.toString (Thread.currentThread(). GetStackTrace()); достаточно просто. – Ajay

ответ

953

Вы можете использовать Thread .currentThread().getStackTrace().

Это возвращает массив StackTraceElement s, представляющий текущую трассировку стека программы.

+35

Классный однострочный, если вы уже используете apache commons для получения строки: 'String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace (e);' http://stackoverflow.com/a/10620951/11236 – ripper234

+4

Первым элементом (индекс 0) в массиве является метод java.lang.Thread.getStackTrace, второй (индекс 1) обычно является первым интересом. – lilalinux

+111

Один лайнер для преобразования трассировки стека в строку, которая работает, когда у вас нет исключения, и вы не используете Apache Arrays.toString (Thread.currentThread(). GetStackTrace()) – Tony

5
try { 
} 
catch(Exception e) { 
    StackTraceElement[] traceElements = e.getStackTrace(); 
    //... 
} 

или

Thread.currentThread().getStackTrace() 
+0

Не будет ли ваш верхний пример давать трассировку стека относительно блока try/catch? –

+0

reallyy-o it will – butterchicken

17

Чтобы получить трассировки стека всех потоков вы можете использовать утилиту jstack, JConsole или послать сигнал убить -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();

+2

Фрагмент кода в этом ответе ближайший к программному генератору типа дампа, который вы видите при отправке JVM сигнала QUIT (в системах Unix) или на Windows. В отличие от других ответов вы можете увидеть мониторы и синхронизаторы, а также трассировки стека (например, если вы перебираете массив StackTraceElement и делаете 'System.err.println (elems [i]) на каждом). Во второй строке в фрагменте отсутствует 'bean.' перед' dumpAllThreads', но я думаю, что большинство людей могут это исправить. –

+0

Спасибо, Джордж - изменил мой пример кода. – Adamski

218
Thread.currentThread().getStackTrace(); 

прекрасно, если вам все равно, что такое первый элемент стека.

new Throwable().getStackTrace(); 

будет иметь определенное положение для вашего текущего метода, если это имеет значение.

+29

'(new Throwable()). GetStackTrace()' также выполняется быстрее (см. Http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6375302) – MightyE

+2

Можете ли вы подробнее объяснить, как результаты Thread.currentThread(). GetStackTrace() может отличаться от нового метода Throwable(). GetStackTrace()? Я попробовал оба и обнаружил, что Thread.currentThread(). GetStackTrace() возвращает массив am с Thread.getStackTrace в индекс 0, а метод вызова - в индекс 1. Новый метод Throwable(). GetStackTrace() возвращает массив с вызовом метод в индексе 0. Кажется, что оба метода имеют определенную позицию для текущего метода, но позиции разные. Есть ли другая разница, которую вы указываете? – Ryan

+8

@Ryan, нет гарантии, что Thread.currentThread(). GetStackTrace() не обещает поддерживать эту позицию в разных версиях метода. Поэтому, когда вы проверяете, что это было в индексе 1. На какой-то версии JVM (1.5 или 1.6, не помните) для Sun это был индекс 2. Это то, что я имею в виду под определенной позицией - спецификация вызывает он будет там и останется там в будущем. – Yishai

52
Thread.currentThread().getStackTrace(); 

можно приобрести с JDK1.5.

Для более старой версии, вы можете перенаправить exception.printStackTrace() к StringWriter():

StringWriter sw = new StringWriter(); 
new Throwable("").printStackTrace(new PrintWriter(sw)); 
String stackTrace = sw.toString(); 
+0

'new Throwable(). GetStackTrace()' доступен с JDK1.4 ... – Holger

151
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) { 
    System.out.println(ste); 
} 
+12

В java есть метод printStackTrace, определенный на Throwable, вы можете сделать: 'new Exception () .printStackTrace (System.out) ', который я помню, цикл for, вероятно, имеет меньшие накладные расходы, но вы должны использовать это только как отладочную вещь ... – Jaap

+0

Мне нравится это лучше всего, потому что у вас есть шанс вычеркнуть шум, обернув инструкцию println, например 'для (. StackTraceElement Ste: Thread.currentThread() getStackTrace()) { , если (. Ste.toString() содержит ("mypackages")) { System.out.println (STE); } } ' – nby

20

На андроид гораздо более простой способ заключается в использовании этого:

import android.util.Log; 
String stackTrace = Log.getStackTraceString(exception); 
+4

Где определена getStackTraceString? Это из библиотеки журналов третьей стороны? – skiphoppy

+6

android.util.Log.getStackTraceString http://developer.android.com/reference/android/util/Log.html –

6

У меня есть служебный метод который возвращает строку с помощью 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(); 
} 

И только логит как ...

... 
catch (FileNotFoundException e) { 
    logger.config(getStackTrace(e)); 
} 
+0

Это похоже на один авто, созданный Netbeans. –

+0

- это logger, встроенный в logger или тот, который вы создали и записываете в файл. –

+0

@ Doug Hauf, logger - это ссылка на встроенный Java Logger. Убедитесь, что вы настроили файл logging.properties. Добавьте его в начале своего класса следующим образом: private static final Logger logger = Logger.getLogger (Your_Class_Name.class.getName()); –

32

Вы можете использовать обыкновенные Apache для что:

String fullStackTrace = org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e); 
+13

Это приятное однострочное решение. FYI, для любого пользователя, использующего 'org.apache.commons.lang3', полная строка:' org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace (e); ' – fileoffset

+2

Просто повторить комментарий fileoffset при переходе на' org .apache.commons.lang3', который я изначально забыл - импорт использует 'lang3' вместо' lang' и заменяет 'getFullStackTrace'' getStackTrace'. – ggkmath

3

Может быть, вы могли бы попробовать это:

catch(Exception e) 
{ 
    StringWriter writer = new StringWriter(); 
    PrintWriter pw = new PrintWriter(writer); 
    e.printStackTrace(pw); 
    String errorDetail = writer.toString(); 
} 

Строка 'ErrorDetail' содержит стек.

7

В строке с гуавы:

Throwables.getStackTraceAsString(new Throwable()) 
12

Другое решение (только 31 символов):

new Exception().printStackTrace(); 
new Error().printStackTrace(); 
+0

Удивительное решение. Теперь мне не нужно перебирать все фреймы стека. –

3
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); 

Последний элемент массива представляет собой нижнюю часть stack, который является наименее недавним вызовом метода в последовательности.

A StackTraceElement has getClassName(), getFileName(), getLineNumber() and getMethodName(). 

петля через StackTraceElement и получить желаемый результат.

for (StackTraceElement ste : stackTraceElements) 
{ 
    //do your stuff here... 
} 
+0

Спасибо, что упомянул последний элемент, содержащий последние. Контринтуитивный и спас меня некоторое время. – clearlight

+0

также .toString() будет выводить все эти данные в строку – Vlad

-1

Это старый пост, но вот мое решение:

Thread.currentThread().dumpStack(); 

Больше информации и больше методов там: http://javarevisited.blogspot.fr/2013/04/how-to-get-current-stack-trace-in-java-thread.html

+2

Так как Thread.dumpStack() является статическим, вы должны просто вызвать его напрямую. –

+2

OP указал, что они хотят ссылаться на код на трассировку стека, а не распечатывать его. –

+0

как @DavidAvendasora упоминал, что вы должны называть 'Thread.dumpStack()' непосредственно, потому что его статический метод. –

0

Вы можете использовать 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] [[email protected]]<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 
3

В 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); 
} 
5

Тони, как комментарий к принятому ответу, дали то, что, кажется, самый лучший ответ, который на самом деле отвечает на вопрос Ора в :

Arrays.toString(Thread.currentThread().getStackTrace()); 

... ОП сделал НЕ спросите, как получить String из трассировки стека от Exception. И хотя я большой поклонник Apache Commons, когда есть что-то простое, как указано выше, нет логической причины использовать внешнюю библиотеку.

+0

У меня есть список тем, и мне нужно распечатать их трассировки стека. –

+0

В этом случае убедитесь, что вы используете 'Thread.getAllStackTraces()', который дает вам «Map '. Hotspot будет защищать все потоки всякий раз, когда это необходимо для обеспечения безопасности. Zing может принести отдельные потоки в безопасное место, не нарушая других. Получение stacktrace требует safepoint. 'Thread.getAllStackTraces()' получает все трассировки стека и останавливает все потоки только один раз. Конечно, вы должны выяснить, какое отображение вы действительно интересуете. –

-1

System.out.println(Arrays.toString(Thread.currentThread().getStackTrace()));

Это поможет вам напечатать трассировки стека без цикла.

+0

Ваш ответ тот же, что и мой, опубликованный 3 месяца назад. –

4

Я полагаю, что

Thread.dumpStack() 

является более простым способом и имеет преимущество фактически не построив исключение или Throwable, когда не может быть проблемой вообще, и значительно больше точки.

+0

Хорошо, на самом деле, dumpStack() является статическим методом и должен быть доступен статическим способом. Спасибо, затмение! –

+0

Мне нравится ярлык, но исходный код для этого метода: 'new Exception (« Stack trace »). PrintStackTrace();' поэтому он фактически создает Throwable – Florent

1

Я использовал ответы от выше и добавил форматирования

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); 
    } 
} 
Смежные вопросы