将Throwable.getStackTrace()的结果转换为描述堆栈跟踪的字符串最简单的方法是什么?


当前回答

使用Java 8流API,您可以执行以下操作:

Stream
    .of(throwable.getStackTrace())
    .map(StackTraceElement::toString)
    .collect(Collectors.joining("\n"));

它将获取堆栈跟踪元素的数组,将它们转换为字符串并连接为多行字符串。

其他回答

这应该是有效的:

StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();

对我来说,最干净、最简单的方法是:

import java.util.Arrays;
Arrays.toString(e.getStackTrace());

老问题,但我想补充一个特殊情况,即您不想打印所有堆栈,通过删除一些您实际上不感兴趣的部分,排除某些类或包。

使用SelectivePrintWriter代替PrintWriter:

// This filters out this package and up.
String packageNameToFilter = "org.springframework";

StringWriter sw = new StringWriter();
PrintWriter pw = new SelectivePrintWriter(sw, packageNameToFilter);
e.printStackTrace(pw);
String sStackTrace = sw.toString(); 
System.out.println(sStackTrace);

其中SelectivePrintWriter类由以下给出:

public class SelectivePrintWriter extends PrintWriter {
    private boolean on = true;
    private static final String AT = "\tat";
    private String internal;

    public SelectivePrintWriter(Writer out, String packageOrClassName) {
        super(out);
        internal = "\tat " + packageOrClassName;
    }

    public void println(Object obj) {
        if (obj instanceof String) {
            String txt = (String) obj;
            if (!txt.startsWith(AT)) on = true;
            else if (txt.startsWith(internal)) on = false;
            if (on) super.println(txt);
        } else {
            super.println(obj);
        }
    }
}

请注意,这个类可能很容易被Regex、contains或其他条件过滤掉。还要注意,这取决于可丢弃的实现细节(不太可能改变,但仍然如此)。

我想知道为什么没有人提到ExceptionUtils.getStackFrames(exception)

对我来说,这是将堆栈跟踪及其所有原因转储到底的最方便方法:

String.join("\n", ExceptionUtils.getStackFrames(exception));

我的oneliner将堆栈跟踪转换为封闭的多行字符串:

Stream.of(e.getStackTrace()).map((a) -> a.toString()).collect(Collectors.joining("\n", "[", "]"))

易于传递给记录器“原样”。