打印异常的堆栈跟踪

102

如何将异常的堆栈跟踪打印到除了stderr之外的流中? 我发现一种方式是使用getStackTrace()并将整个列表打印到流中。


如果你想将异常跟踪作为字符串获取,可以调用Throwable(异常)的getStackTrace方法,该方法将返回一个StackTraceElement对象数组,你可以将其组合成一个字符串(使用该对象的toString方法来获取一行跟踪信息)。 - jcubic
10个回答

91

4
@FranklinYu,这个问题的核心在于他不想将内容打印到stderr,而是另一个任意的流中。 - Mike Deck
你可以使用 e.printStackTrace(new PrintStream("path.txt")) 代替 System.out - Mauricio Gracia Gutierrez

88

虽然不太美观,但仍是一个解决方案:

StringWriter writer = new StringWriter();
PrintWriter printWriter = new PrintWriter( writer );
exception.printStackTrace( printWriter );
printWriter.flush();

String stackTrace = writer.toString();

3
这正是我需要的(尽管使用它让我感觉很肮脏!) - Henley

68

Throwable.printStackTrace(..) 可以接受一个 PrintWriterPrintStream 参数:

} catch (Exception ex) {
    ex.printStackTrace(new java.io.PrintStream(yourOutputStream));
}

话虽如此,考虑使用像SLF4J这样的日志记录器接口,搭配使用LOGBacklog4j等日志记录实现。


2
我们如何使用log4j打印这个?log.error(ex.printStackTrace())? - Geoff Langenderfer

13

针对Android开发最简洁的方法:Log.getStackTraceString(exception)


1
你不能使用这个来向任意流输出打印信息。只有在配置了日志记录器的情况下才有用。 - r.v
我喜欢这种极简主义的方法,但它与我的slf4j不兼容 :( - killjoy

12

虽然这个答案看起来非常正确,但它并不是问题的答案。OP问如何将堆栈跟踪打印到另一个流中。 - Buurman
尽管这可能不能回答OP的问题,但我认为这是将异常作为字符串的最佳方式,使用一个非常成熟的格式。谢谢! - Clint Eastwood

10

我创建了一个方法,可以帮助获取堆栈跟踪:

private static String getStackTrace(Exception ex) {
    StringBuffer sb = new StringBuffer(500);
    StackTraceElement[] st = ex.getStackTrace();
    sb.append(ex.getClass().getName() + ": " + ex.getMessage() + "\n");
    for (int i = 0; i < st.length; i++) {
      sb.append("\t at " + st[i].toString() + "\n");
    }
    return sb.toString();
}

3

Throwable类提供了两种方法,分别是printStackTracePrintWriter以及PrintStream,可以将堆栈跟踪输出到给定的流中。建议使用其中之一。


2

使用 slf4j,例如通过 lombok@Slf4j 注解

log.error("error", e);


1

请查看javadoc

out = some stream ...
try
{
}
catch ( Exception cause )
{
      cause . printStrackTrace ( new PrintStream ( out ) ) ;
}

0

如果您对更紧凑的堆栈跟踪感兴趣,并且带有更多信息(包详细信息),则它看起来像:

  java.net.SocketTimeoutException:Receive timed out
    at j.n.PlainDatagramSocketImpl.receive0(Native Method)[na:1.8.0_151]
    at j.n.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:143)[^]
    at j.n.DatagramSocket.receive(DatagramSocket.java:812)[^]
    at o.s.n.SntpClient.requestTime(SntpClient.java:213)[classes/]
    at o.s.n.SntpClient$1.call(^:145)[^]
    at ^.call(^:134)[^]
    at o.s.f.SyncRetryExecutor.call(SyncRetryExecutor.java:124)[^]
    at o.s.f.RetryPolicy.call(RetryPolicy.java:105)[^]
    at o.s.f.SyncRetryExecutor.call(SyncRetryExecutor.java:59)[^]
    at o.s.n.SntpClient.requestTimeHA(SntpClient.java:134)[^]
    at ^.requestTimeHA(^:122)[^]
    at o.s.n.SntpClientTest.test2h(SntpClientTest.java:89)[test-classes/]
    at s.r.NativeMethodAccessorImpl.invoke0(Native Method)[na:1.8.0_151]

你可以尝试使用Throwables.writeTo来自spf4j库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接