java - 为什么异常. printStackTrace() 被认为是不好的实践?

有很多证据表明打印异常的堆栈跟踪是不好的做法。

例如,在Checkstyle中检查RegexpSingleline :

这个检查可用于查找常见的不良做法,例如调用ex.printStacktrace()

但是,我很难找到任何能够提供正确理由的地方,因为堆栈跟踪在跟踪导致异常的原因时非常有用。我知道的内容:

1)堆栈跟踪永远不应对最终用户可见(出于用户体验和安全目的)

2)生成堆栈跟踪是一个相对昂贵的过程(尽管大多数情况下都不可能出现问题),

3)许多日志记录框架将为您打印堆栈跟踪(我们不能轻易改变它),

4)打印堆栈跟踪不构成错误处理。它应该与其他信息日志记录和异常处理相结合。

避免在代码中打印堆栈跟踪的其他原因是什么?

时间:

你正在触碰多个问题:

1)堆栈跟踪永远不应对最终用户可见(出于用户体验和安全目的)

是的,应该可以访问它来诊断最终用户的问题,但是,最终用户不应该看到它们有两个原因:

  • 它们非常模糊和不可读,应用程序看起来非常不友好,
  • 向最终用户显示堆栈跟踪可能会带来潜在的安全风险,纠正我,如果我错了,PHP实际上在堆栈跟踪中打印函数参数 - 很棒,但是,非常危险 - 如果你在连接数据库时遇到异常,你有什么不会显示在堆栈跟踪中?

2)生成堆栈跟踪是一个相对昂贵的过程(尽管大多数情况下都不可能出现问题),

在创建/抛出异常时产生堆栈跟踪,打印它不那么昂贵,实际上,你可以在定制异常中重写Throwable#fillInStackTrace(),使得抛出异常几乎与简单的GOTO语句一样便宜。

3)许多日志记录框架将为您打印堆栈跟踪(我们不能轻易地更改它),

非常好的问题,这里的主要问题是: 如果框架为您记录异常,则不执行任何操作(但请确保这样),如果您想自己记录异常,请使用Logback或Log4J之类的日志框架,而不要将它们放在原始控制台上,因为它很难控制 它。

使用日志框架,可以轻松地将堆栈跟踪重定向到文件,控制台,甚至将它们发送到指定的E-mail地址,使用硬编码printStackTrace(),你必须使用sysout

4)打印堆栈跟踪不构成错误处理,它应该与其他信息日志记录和异常处理相结合。

再次:正确地记录SQLException,并显示好的(使用完整的堆栈跟踪,使用日志框架): "抱歉,我们目前无法处理你的请求"消息,你真的认为用户对原因感兴趣? 你是否看到StackOverflow错误屏幕? 很幽默但不透露任何细节,

但是,他会立即给你打电话,你需要能够诊断出问题。因此,你需要两个:正确的异常日志记录和用户友好消息。


总是记录异常(最好使用日志框架 ),但是,不要将它们公开给最终用户,在GUI中仔细考虑错误消息,只在开发模式中显示堆栈跟踪。

首先,printStackTrace()并不昂贵,因为当自己创建异常时,堆栈跟踪会被填充。

我们的想法是通过logger framework传递任何记录日志,以便可以控制日志记录。因此不要使用printStackTrace只使用Logger.log(msg, exception);之类

printStackTrace()打印到控制台,在生产环境中,任何人都不会看到,是正确的,应该将此信息传递给logger 。

我认为你的理由清单非常全面。

我多次遇到的一个非常糟糕的例子是这样的:


 try {
 // do stuff
 } catch (Exception e) {
 e.printStackTrace(); // and swallow the exception
 }

上述代码的问题在于,处理完全由printStackTrace调用组成: 异常并没有真正处理,也不允许退出。

另一方面,随着代码中出现意外的异常,我总是记录堆栈跟踪,过去几年,这个策略为我节省了大量的调试时间。

在服务器应用程序中,stacktrace会爆炸你的stdout/stderr文件,它可能变得越来越大,并且充满了无用的数据,因为通常没有上下文,没有时间戳等。

例如当使用tomcat作为容器时catalina.out

...