Ответ 1
Вы также можете попробовать Thread.getAllStackTraces()
получить карту трассировок стека для всех живых потоков.
Я собираюсь создать инструмент отладки для моего приложения Java.
Мне интересно, можно ли получить трассировку стека, точно так же, как Exception.printStackTrace()
, но при этом не исключая исключения?
Моя цель состоит в том, чтобы в любом заданном методе выгрузить стек, чтобы узнать, кто является вызывающим методом.
Вы также можете попробовать Thread.getAllStackTraces()
получить карту трассировок стека для всех живых потоков.
Да, просто используйте
Thread.dumpStack()
Если вам нужна трассировка только для текущего потока (а не для всех потоков в системе, как это предлагает Ram), выполните:
Thread.currentThread(). getStackTrace()
Чтобы найти вызывающего абонента, выполните:
private String getCallingMethodName() {
StackTraceElement callingFrame = Thread.currentThread().getStackTrace()[4];
return callingFrame.getMethodName();
}
И вызовите этот метод из метода, который должен знать, кто его вызывающий. Однако слово предупреждения: индекс вызывающего кадра в списке может меняться в зависимости от JVM! Все зависит от того, сколько слоев вызовов есть в getStackTrace, прежде чем вы достигнете точки, где генерируется трассировка. Более надежным решением было бы получить трассировку и повторить ее поиск кадра для getCallingMethodName, а затем выполнить два шага дальше, чтобы найти истинного вызывающего.
Вы можете получить трассировку стека следующим образом:
Throwable t = new Throwable();
t.printStackTrace();
Если вы хотите получить доступ к фрейму, вы можете использовать t.getStackTrace() для получения массива кадров стека.
Имейте в виду, что в этой stacktrace (как и любой другой) могут отсутствовать некоторые фреймы, если компилятор hotspot был занят оптимизацией.
Обратите внимание, что Thread.dumpStack() действительно генерирует исключение:
new Exception("Stack trace").printStackTrace();
Вы также можете отправить сигнал JVM для выполнения Thread.getAllStackTraces() в запущенном Java-процессе, отправив сигнал QUIT в процесс.
В Unix/Linux используйте:
kill -QUIT process_id
, где process_id - это номер процесса вашей Java-программы.
В Windows вы можете нажать Ctrl-Break в приложении, хотя обычно вы этого не увидите, если не используете консольный процесс.
JDK6 представила еще один вариант - команду jstack, которая отобразит стек из любого запущенного процесса JDK6 на вашем компьютере:
jstack [-l] <pid>
Эти параметры очень полезны для приложений, работающих в рабочей среде и не могут быть легко изменены. Они особенно полезны для диагностики тупиков времени выполнения или проблем с производительностью.
http://java.sun.com/developer/technicalArticles/Programming/Stacktrace/ http://java.sun.com/javase/6/docs/technotes/tools/share/jstack.html
Если вам нужен вывод захвата
StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
Вам даже не нужно делать это в коде. Вы можете присоединить Java HPROF к вашему процессу и в любой момент нажать Control- \, чтобы вывести кучу кучи, запустить потоки и т.д., без изменения вашего кода приложения. Это немного устарело, Java 6 поставляется с консолью GUI, но я по-прежнему считаю, что HPROF очень полезен.
Java 9 представила StackWalker
и поддерживает классы для ходьбы по стеку.
Вот несколько фрагментов из Javadoc:
Метод
walk
открывает последовательный потокStackFrames
для текущего потока, а затем применяет данную функцию для перемещения потокаStackFrame
. Поток сообщает элементы кадрового кадра по порядку, начиная с самого верхнего кадра, который представляет точку выполнения, в которой стек был сгенерирован до самого нижнего кадра. ПотокStackFrame
закрывается при возврате метода ходьбы. Если попытка повторного использования закрытого потока будет выбранаIllegalStateException
....
Чтобы сделать снимок 10 лучших кадров стека текущего потока,
List<StackFrame> stack = StackWalker.getInstance().walk(s -> s.limit(10).collect(Collectors.toList()));