如何在Java中获取当前堆栈跟踪?

如何在Java中获得当前的堆栈跟踪,例如如何在. NET中执行#0

我找到了Thread.dumpStack(),但它不是我想要的-我想找回堆栈跟踪,而不是打印出来。

628613 次浏览

您可以使用Thread.currentThread().getStackTrace()

它返回一个#0数组,表示程序的当前堆栈跟踪。

愚蠢的我,这是Thread.currentThread().getStackTrace();

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

Thread.currentThread().getStackTrace()

要获取所有线程的堆栈跟踪,您可以使用jstack实用程序、JConsole或发送杀死-退出信号(在Po的操作系统上)。

但是,如果您想以编程方式执行此操作,您可以尝试使用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()

StackTraceElement[] st = Thread.currentThread().getStackTrace();

如果你不关心堆栈的第一个元素是什么,这很好。

StackTraceElement[] st = new Throwable().getStackTrace();

将为您的当前方法定义一个位置,如果这很重要的话。

Thread.currentThread().getStackTrace();

从JDK1.5开始可用。

对于旧版本,您可以将exception.printStackTrace()重定向到StringWriter()

StringWriter sw = new StringWriter();new Throwable("").printStackTrace(new PrintWriter(sw));String stackTrace = sw.toString();
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {System.out.println(ste + "\n");}

在android上,一个更简单的方法是使用这个:

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

我有一个实用方法,它返回一个带有堆栈跟踪的字符串:

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

您可以使用Apache的共享资源:

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

也许你可以试试这个:

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

字符串'error Detail'包含堆栈跟踪。

用番石榴串:

Throwables.getStackTraceAsString(new Throwable())

另一种解决方案(仅35 31个字符):

new Exception().printStackTrace();new Error().printStackTrace();
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();

数组的最后一个元素表示堆栈的底部,这是序列中最近的方法调用。

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

遍历StackTraceElement并获得所需的结果。

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

这是一篇旧文章,但这是我的解决方案:

Thread.currentThread().dumpStack();

更多信息和更多方法:http://javarevisited.blogspot.fr/2013/04/how-to-get-current-stack-trace-in-java-thread.html

如果您想检查进程的当前调用堆栈,您可以使用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

在Java9有一个新方法:

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

托尼,作为对公认答案的评论,给出了似乎是最好的答案,实际上是答案OP的问题

Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );

……OP确实不是询问如何从Exception的堆栈跟踪中获取String。尽管我是Apache Commons的忠实粉丝,但当有像上面这样简单的东西时,没有逻辑理由使用外部库。

我建议

  Thread.dumpStack()

是一种更简单的方法,并且具有在可能根本没有问题的情况下不实际构建异常或throwable的优点,并且更加切题。

我使用了上面的答案并添加了格式

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

获取堆栈跟踪:

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);

对于那些只想将当前堆栈跟踪到他们的日志的人来说,我会选择:

getLogger().debug("Message", new Throwable());

干杯

你也可以使用异常来打印堆栈,而不是把新的行字符:

Exception e = new Exception();e.setStackTrace(Thread.currentThread().getStackTrace());loggr.info(e);