Як отримати поточний слід стека на Java, як, наприклад, у .NET, який ви можете зробити Environment.StackTrace
?
Я знайшов, Thread.dumpStack()
але це не те, що я хочу - я хочу повернути слід стека, а не роздрукувати його.
Як отримати поточний слід стека на Java, як, наприклад, у .NET, який ви можете зробити Environment.StackTrace
?
Я знайшов, Thread.dumpStack()
але це не те, що я хочу - я хочу повернути слід стека, а не роздрукувати його.
Відповіді:
Можна використовувати Thread.currentThread().getStackTrace()
.
Це повертає масив StackTraceElement
s, який представляє поточний слід стека програми.
String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e);
stackoverflow.com/a/10620951/11236
new Throwable().getStackTrace()
це набагато швидше, тому що йому не потрібно перевіряти this != Thread.currentThread()
та обминати потенційні накладні витрати JVM, щоб викликати це через дитячий клас ( 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' );
... ОП НЕ запитав, як отримати String
сліди стека від Exception
. І хоча я великий шанувальник Apache Commons, коли є щось таке просте, як вище, немає логічної причини використовувати зовнішню бібліотеку.
Thread.getAllStackTraces()
що дає вам Map<Thread, StackTraceElement[]>
. Точка доступу захистить всі потоки, коли це потрібно для безпечної точки. Цінг може підвести окремі нитки до безпечної точки, не заважаючи іншим. Отримати стек-трек потрібно безпечну точку. 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 дозволяє вам динамічно змінювати форматування оператора журналу під час його введення. Наскільки мені відомо, 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()));
Це допоможе вам надрукувати слід стека без циклу.