e.printStackTrace()在未知异常情况下有什么问题?

11

如果在已知异常的情况下使用日志记录器,那么对于未知异常使用 e.printStackTrace() 有什么问题吗?

我经常被告知不要这样做,但没有给出原因。

以下是示例:

try {
            dostuff();
        } catch (AException ae) {
            logger.error("ae happened");
        } catch (BException be) {
            logger.error("be happened");
        } catch (CException ce) {
            logger.error("ce happened");
        } catch (Exception e) {
            e.printStackTrace();
        }
6个回答

15

因为它不使用记录器系统,直接输出到stderr,需要避免。

编辑:为什么要避免直接写入stderr?

回答@shinynewbike的问题,我稍微修改了我的答案。需要避免的是直接写入stderr而不使用记录器功能。

记录器提供有用的功能来通过优先级和包更改日志跟踪,此外,它们还允许将跟踪重定向到不同的输出机制...队列、文件、数据库、流等。

当您直接写入System.errSystem.out时,然后您会失去这些功能,更糟糕的是,如果您混合使用loggerSystem.err.write,则可能会在不同的“文件”中获得跟踪信息,这将使您的系统调试困难重重。


我想你的意思是 stderr 或者 System.err ;) - Peter Lawrey
因为记录器已配置为监视它,所以没有人会看到stderr。 - jmj
@shinynewbike,请查看答案的新版本,希望能够澄清。 - Manuel Salvadores

7

在我看来,你应该

  • 始终记录到日志程序或标准错误输出,但不要混合两者(也许这是投诉的原因)
  • 除非你确定不需要它,否则总是记录异常及其堆栈跟踪信息。

3
这很糟糕,因为e.printStackTrace()不一定会写入与logger.error()相同的日志文件,为了保持一致性,您应该对所有内容使用logger.error()e.printStackTrace()也无法描述导致错误的具体情况。您应该始终包含一个日志消息,以便读取日志文件的人清楚地了解发生了什么错误。
如果将异常对象作为第二个参数发送,并且您将在日志文件中获取堆栈跟踪以及异常的消息字符串。阅读日志文件的人将很高兴拥有这些信息。
try {
    doStuff();
}
catch (AException ae) {

    // Send to the log file a message describing what we were doing,
    // and what happened as a result

    logger.error("ae happened, while attempting to do stuff, but that's okay", ae);

    dealWithTheSituation();
}
catch (Exception e) {

    logger.fatal("an unexpected error happened, while attempting to do stuff, cannot proceed", e);

    abortAndCatchFire();  // Burn the evidence
}

1
很好的实际例子,而且9年后仍然具有参考价值。 - Cobie Fisher

2
日志框架为您提供的一个强大的抽象是最终输出日志消息的位置。您可能认为使用标准输出和标准错误流可以实现相同的效果,但并非总是如此。在许多环境中,开发人员无法控制应用程序中标准io流的操作。
最常见的情况是您的应用程序在另一个容器(例如tomcat)内运行,该容器可能会将自己的消息输出到标准输出。由于您的应用程序在同一进程中运行,所有消息都将与容器的混合在一起,以及在同一容器中运行的任何其他应用程序的消息。
使用日志记录库使您的应用程序能够灵活地将消息记录到许多不同的目的地,这些目的地可以由部署者进行配置。当您使用e.printStackTrace()时,您将无法获得此好处。
顺便说一下,您所提供的示例引发了一些其他问题。一些后续问题可能包括:
- 什么时候可以使用catch(Exception ex)? - 异常应该在何时/如何记录?

1

catch (Exception e) 捕获所有异常,包括从 RuntimeException 派生的未检查异常,例如 NullPointerExceptionIndexOutOfBoundsException,程序继续运行,尽管很可能您不希望这样做,因为这些异常通常是致命的,并且可能在意料之外的位置退出控制流。

如果您期望其中一种未检查的异常,则应明确捕获该类型的异常并处理它。


0
首先,打印堆栈跟踪并不能解决问题,而且问题可能不会报告给父线程进行进一步处理。我的建议是在catch子句中处理异常,通过使用e.getClass().getName()来识别程序中的异常类型。

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