【问题标题】:What's wrong with using System.err in Java?在 Java 中使用 System.err 有什么问题?
【发布时间】:2010-11-06 04:39:22
【问题描述】:

我正在对我的 Java 代码使用 Enerjy (http://www.enerjy.com/) 静态代码分析器工具。它告诉我以下行:

System.err.println("忽略那个数据库");

不好,因为它使用 System.err。确切的错误是:“JAVA0267 Use of System.err”

使用 System.err 有什么问题?

【问题讨论】:

    标签: java static-analysis stderr


    【解决方案1】:

    简短回答:将其用于记录目的被认为是一种不好的做法。

    据观察,在没有广泛可用/接受的日志框架的旧时代,每个人都使用 System.err 将错误消息和堆栈跟踪打印到控制台。这种方法可能适用于开发和本地测试阶段,但不适用于生产环境,因为您可能会丢失重要的错误消息。因此,在当今几乎所有静态分析工具中,都会检测到此类代码并将其标记为不良做法(或类似名称的问题)。

    日志框架反过来提供结构化和逻辑的方式来记录您的事件和错误消息,因为它们可以将消息存储在各种持久位置(日志文件、日志数据库等)。

    最明显的(并且没有外部依赖)hack 解决方案是通过java.util.logging.Logger 类使用内置的Java Logging 框架,因为它默认将日志事件转发到控制台。例如:

    final Logger log = Logger.getLogger(getClass().getName());
    ...
    log.log(Level.ERROR, "Something went wrong", theException);
    

    (或者您可以关闭该分析选项)

    【讨论】:

    • 另外 System.err 不包括消息来自何处的信息。因此,您需要依靠人类读者来确定应该做什么(如果有的话)。
    • @kd304 “因为您可能会丢失重要的错误消息” 为什么?有没有要去控制台?我错过了什么?
    • @kd304 “(或者您可以关闭该分析选项)”是什么意思?
    • @kd304,Geek 有一个有效的问题......为什么你说我们可能会丢失System.err 的重要错误消息?
    【解决方案2】:

    System.err 实际上更多的是用于调试目的。最好以对用户更友好的方式进行适当的异常处理和错误处理。如果用户想要看到错误,请改用 System.out.println。

    如果您想从开发人员的角度跟踪这些错误,您应该使用记录器。

    【讨论】:

      【解决方案3】:

      你的错误描述是:

      System.err 的使用可能表示残留的调试或样板代码。考虑使用一个 用于处理错误日志的全功能日志包,例如 Apache Commons。

      您似乎正在使用 System.err 进行日志记录,原因如下:

      • 如果不修改应用程序二进制文件,就不可能在运行时启用日志记录
      • 无法通过编辑配置文件来控制日志记录行为
      • 可能还有很多人

      【讨论】:

        【解决方案4】:

        写入 System.err 的内容通常会在运行时丢失,因此使用更灵活的日志框架被认为是一种更好的做法,该框架可以更灵活地输出消息的位置,以便将其存储为文件并进行分析。

        非控制台应用程序的 System.err 和 System.out 只有在其 IDE 中运行代码的开发人员才能看到,如果在生产环境中触发该项目,有用的信息可能会丢失。

        【讨论】:

        • “写入 System.err 的内容通常会在运行时丢失”--如何?
        • @Geek,因为当应用程序关闭时控制台消失了,或者一开始就永远不可见。
        【解决方案5】:

        虽然我同意上述关于使用日志框架的观点,但我仍然倾向于在一个地方使用System.err 输出:在关闭挂钩中。这是因为我发现在使用java.util.logging 框架时,如果日志语句出现在关闭挂钩中,它们并不总是显示出来。这是因为日志库可能包含自己的关闭挂钩来清理日志文件和其他资源,并且由于您不能依赖关闭挂钩运行的顺序,因此您不能依赖 java.util.logging 语句按预期工作。

        查看此链接(“评论”部分)了解更多信息。

        http://weblogs.java.net/blog/dwalend/archive/2004/05/shutdown_hooks_2.html

        (显然,另一种选择是使用不同的日志框架。)

        【讨论】:

        • +1 很高兴知道,谢谢。不过,我宁愿避免在我的应用程序中使用关闭挂钩。
        【解决方案6】:

        System.err.println 和 System.out.println 不应用作日志接口。 STD-Output 和 STD-Error(由 System.out 和 .err 编写)用于来自命令行工具的消息。

        【讨论】:

          【解决方案7】:

          System.err 打印到控制台。这可能适合学生测试他们的作业,但不适用于不会看到这些消息的应用程序(控制台只存储这么多行)。

          更好的方法是抛出一个异常来保存通常会发送到控制台的消息。另一种方法是使用第三方日志记录软件,该软件会将此消息存储在可以永久存储的文件中。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-11-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多