如何在捕获异常时显示堆栈跟踪?

33

我有一个通用的函数,用于打印异常(使用log4j):

private void _showErrorMessage(Exception e) {
    log.error(e.getClass() + ": " +  e.getMessage() + ": " + e.getCause() + "\n" +  e.getStackTrace().toString());
}

我看到的不是堆栈跟踪,而是:

[Ljava.lang.StackTraceElement;@49af7e68

我如何正确查看异常的堆栈跟踪信息?

更新

log.error(e) <- 显示错误,但不显示堆栈跟踪信息。


8
在log4j中调用log.error(e)方法会调用错误版本的方法 (http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Category.html#error%28java.lang.Object%29)。该方法的JavaDoc甚至提到了这个事实: "警告:请注意,向此方法传递Throwable将打印Throwable的名称但不包括堆栈跟踪信息。要打印堆栈跟踪,请改用error(Object, Throwable)形式。" - Joachim Sauer
5
调用log.error(e,e)即可完成该任务 ;) - Guillaume
7个回答

78

你的日志框架应该具备记录异常的能力,因此只需将异常传递给相应的 .error(Object, Throwable) 方法即可:

如果你的日志框架不能这样做,或者因为其他原因需要将堆栈跟踪转化为字符串,那么就有些困难了。你必须创建一个包装 StringWriterPrintWriter 并在 Exception 上调用 .printStackTrace()

StringWriter sw = new StringWriter();
ex.printStackTrace(new PrintWriter(sw));
String stacktrace = sw.toString();

当我将异常传递给log.error时,它只显示错误消息而没有堆栈跟踪。使用log4j。 - ufk
1
这意味着您调用了错误的版本。有error(Object)error(Object,Throwable)两个版本。调用第一个版本将有效地调用toString() - Joachim Sauer
@Joachim,处理log4j异常的方法是使用log.error(String, Throwable)记录日志,并让log4j处理堆栈跟踪。提问者显然不知道这一点。 - Thorbjørn Ravn Andersen
@Joachim,抱歉。看起来log4j信息是在你回答后编辑添加的。 - Thorbjørn Ravn Andersen

20

你尝试了吗?

private void _showErrorMessage(Exception e) {
    log.error("Hey! got an exception", e);
}

14

2
@codemonkey,你可以在你最喜欢的搜索引擎中搜索ExceptionUtils:我的回答是使用现有的库。我无法维护我在SO上发布的所有链接。现在,Joachim的答案听起来比我的更好:) 请阅读它。 - Guillaume

5

Throwable.getStackTrace 返回一个 StackTraceElement 数组,因此 toString 方法返回的是数组本身的文本表示。

要实际检索堆栈跟踪信息,需要遍历每个 StackTraceElement 以获取更多信息。


4
你可以查看谷歌的Guava库。 Throwables.getStackTraceAsString(Throwable throwable)方法。

1

关于你的问题,确切的答案是你应该这样调用Log4J:

private void _showErrorMessage(Exception e) {
    log.error(e.getClass() + ": " +  e.getMessage() + ": " + e.getCause(), e);
}

虽然我会省略对 e.getCause() 的调用,因为堆栈跟踪会自动提供它:

private void _showErrorMessage(Exception e) {
    log.error(e.getClass() + ": " +  e.getMessage(), e);
}

如果你真的需要堆栈跟踪字符串,那么ExceptionUtils是可以的,但由于你正在使用Log4J,如果不利用其内置的异常处理功能,你会失去很多。


1

异常堆栈追踪日志记录提供了两种方法来实现这一目的,一种是基于Apache Commons的方法,另一种使用标准JDK的方法。


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