何时记录已捕获异常的堆栈跟踪

6
我最近问了是否报告捕获异常的getMessage()文本。令人惊讶的是,大多数答案误解了我的问题,并认为我在问是否要报告捕获异常的堆栈跟踪,暗示这样做是被认为是正常的。所以我提出了一个后续问题。
在什么情况下,当你catch一个异常时,你应该或者不应该报告一个堆栈跟踪?通过“报告”,我包括要求日志框架记录堆栈跟踪
我不是在问是否要报告某些东西。我在问那个报告是否应该包括堆栈跟踪。
6个回答

9
我个人遵守以下规则:
  • 如果我可以在catch中以可恢复的方式处理异常(例如DateFormatException),则无需跟踪堆栈

  • 如果我想要重新抛出异常,不记录堆栈跟踪。(以链接的方式重新抛出以保留此信息)

  • 如果我在catch块中将异常处理为错误情况(例如SQL错误),则记录堆栈跟踪。

  • 如果这是运行时异常,则建议框架(您自己或您使用的任何框架)进行跟踪。


“错误情况”:您能否澄清您认为的错误情况是什么? - Raedwald
"运行时异常":您指的是RuntimeException类的异常,也就是未经检查的异常? - Raedwald
“错误情况”:指任何意外的情况,但很难解释。例如,乐观锁定异常可以是预期的情况(即,您处理它并显示错误),也可以是意外的情况(它不应该发生,致命错误,显示堆栈跟踪),具体取决于情况。“运行时异常”:确切地说,正如您所怀疑的那样。我还要补充一个规则:当存在疑虑时,请追踪堆栈。 - alvi

3

这取决于上下文。例如,当解析来自外部系统的输入时,我可能不会记录/报告NumberFormat引发的ParseException,但如果我捕获到处理系统边界内数据时引发的ParseException,我肯定会这样做,因为这表明内部系统状态存在不一致而不是输入值验证失败。


2
"内部系统状态不一致" = 表示存在错误的迹象。 - Raedwald

3

作为开发者,当你遇到错误情况时,你需要堆栈跟踪信息。因此,你需要一种方法将其从JVM中提取出来并传递给自己。

如果你不将其记录到文件中,那么你该怎么办呢?在JVM中,文件是最可靠的东西,所以你至少应该将其放在那里,然后再发送到网络上。


“在错误情况下”:您能否澄清什么是“错误情况”。只有在捕获未经检查的异常时吗? - Raedwald
@Raedwald,在意料之外出现异常的情况下。mcfinnigan提到了ParserExceptions - 你很可能不想记录这些异常(除非它们发生在意料之外的地方)。 - Thorbjørn Ravn Andersen
所以,您并不是指类Error的异常(http://download.oracle.com/javase/6/docs/api/java/lang/Error.html)。 - Raedwald
@Raedwald,不,在代码未预料到异常的情况下。 当出现未预料到的情况时,您需要尽可能多的帮助来修复它。 - Thorbjørn Ravn Andersen

1

对于想要通过异常来调试错误的程序员来说,堆栈跟踪很有用。但对于其他人而言,方法名和调用顺序是无意义的,冗长的信息只会分散注意力。因此,仅当异常指示程序中存在错误时,才应记录堆栈跟踪。然而,这并不总是意味着您编写的方法应该捕获并记录异常。实际上,未经检查的异常会指示出错误,因此让异常从方法中抛出并在更高层次进行处理通常更容易(也更好):如果您正在使用框架,则它可能会为您记录异常(通常还会提供其他有用信息);JVM本身可能会记录从main抛出的任何异常。


0

我通常报告与GUI无关的异常。GUI异常很常见,在大型Swing程序中经常发生。

一般来说,我对以下内容深感兴趣:与数据库相关的异常、我自己愚蠢的错误异常(数组越界等)以及其他一些我无法处理的事情,比如WebServices等。

我认为这取决于系统的类型,如果是公共系统(如网站),还是私有系统(内部网站、本地GUI)。


“我的愚蠢错误异常”:您是指未经检查的异常吗? - Raedwald
这取决于你报告异常的方式。如果你在try-catch块中进行报告,那么未经检查的异常将很难记录。但是,你可以有更高级别的异常类似,比如给员工ID分配负整数,你可能想要引发一个异常。 - santiagobasulto

-1

我会报告所有的异常。但如果你正在使用log4j,那么你可以控制哪些异常你确定不想在日志中看到。如果特定的用户异常有一个不同的类,则在生产环境中禁用该类的日志记录,并在较低的环境中启用它。这样,你就不需要在代码级别上进行任何报告操作。所有的操作都是在日志框架中抽象出来的。


你在代码层面上没有做任何关于报告的事情:这将决策从编程时间推迟到配置时间,但问题仍然存在:你要为哪个堆栈跟踪报告? - Raedwald
通常我会在异常的构造函数中记录异常日志。在这种情况下,我不需要显式地记录任何内容。一旦我实例化一个异常,它就会被记录。因此,我说过,如果你不想报告特定的异常,请确保在log4j属性中禁用它。对于原始问题,我认为你肯定希望在开发中报告所有异常,然后在生产中禁用大部分异常。 - sethu
我一旦实例化一个异常,它就会被记录下来:这与异常的整个设计初衷相悖,即将错误处理的检测和启动(抛出部分)与处理和报告完成(捕获部分)分离开来。 - Raedwald

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