为什么java.util.logging.Logger打印到stderr?

我有一个简单的设置来记录一条消息:和JDK 8 Update 65Eclipse Mars

import java.util.logging.Logger;

public class Example {

    private final static Logger LOGGER = Logger.getLogger(Example.class.getName());

    public static void main(String[] args) {
        LOGGER.info("Test");
    }

}

我希望在 上获得输出,就像使用 .
但是,它被打印在 上,这导致 eclipse 控制台上的红色字体:stdoutSystem.out.println();stderr

enter image description here

我知道我可以通过编写自定义来更改此行为,但我想知道为什么默认输出出现在 而不是 ?Handlerstderrstdout

记录器应使用 + 和级别。stdoutfineinfostderrsevere


答案 1

java.util.logging API 是在 JSR 47: Logging API Specification 下开发的。根据“建议的最终草案”中的更改日志,ConsoleHandler始终使用System.err。JCP页面还列出了API的原始作者,我认为只有这些名字才能真正知道您问题的答案。

也就是说,我认为起源来自System.err API文档。

通常,此流对应于显示输出或主机环境或用户指定的另一个输出目标。按照惯例,此输出流用于显示应立即引起用户注意的错误消息或其他信息,即使主体输出流(变量 out 的值)已重定向到通常不受持续监视的文件或其他目标也是如此。

反对 System.out

“标准”输出流。此流已打开并准备好接受输出数据。通常,此流对应于显示输出或主机环境或用户指定的另一个输出目标。

日志记录映射到诊断,而不是原始数据。将数据与诊断错误信息分开非常重要,尤其是在管道处理过程中,因为下游消费者只准备接受数据信息,而不是错误消息。有关更多详细信息,请参阅对 stdin、stdout 和 stderr 感到困惑?


答案 2

这是有据可查的。默认情况下,记录器发布到其父级的处理程序,以递归方式发布到树,直到指定了另一个处理程序。您可以遍历父级的处理程序,并查看父级记录器的默认处理程序是 ConsoleHandler,它使用 System.err 发布日志记录。

public class Main {
    public static void main(String[] args) {
        Handler[] handlers = Logger.getLogger(Main.class.getName()).getParent().getHandlers();
        for (Handler handler : handlers) {
            System.out.println(handler.getClass().getName());
        }
    }
}

推荐