java - System.setErr() 干扰 Logger

标签 java java.util.logging

在较大的程序中,我使用静态 java.util.logging.Logger 实例,但将 System.err 连续重定向到多个不同的文件。我第二次尝试重定向 System.err 时,Logger 无法记录。

这是一个显示问题的测试程序:

import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.logging.Logger;

class TestRedirect {
    static final Logger logger = Logger.getLogger("test");

    public static void main(String[] args) throws FileNotFoundException {
        for (int i = 1; i <= 2; i++) {
            TestRedirect ti = new TestRedirect();
            ti.test(i);
        }
    }

    void test(int i) throws FileNotFoundException {
        PrintStream filePrintStream = new PrintStream("test" + i + ".log");
        PrintStream stderr = System.err; // Save stderr stream.
        System.setErr(filePrintStream);  // Redirect stderr to file.
        System.err.println("about to log " + i);
        logger.info("at step " + i);
        System.setErr(stderr);           // Restore stderr stream.
        filePrintStream.close();
    }
}

这是输出:

test1.log:

about to log 1
Jan 28, 2014 4:34:20 PM TestRedirect test
INFO: at step 1

test2.log:

about to log 2

我以为我也会在 test2.log 中看到 Logger 生成的消息。为什么Logger停止工作,我该怎么办?

最佳答案

默认情况下,JRE 配置为在根记录器上加载 ConsoleHandler。默认情况下,您的日志消息将传输到根记录器处理程序。根记录器处理程序是按需加载的。在您当前的程序中,根记录器 ConsoleHandler 的延迟加载正在捕获您的第一个重定向的 System.err。之后,根记录器处理程序永远不会重新加载,这就是为什么您永远不会在日志 2 中看到日志消息的原因。加上第一个重定向流已关闭,因此现在根 ConsoleHandler 正在写入关闭的流。

为了证明这一点,请将以下内容添加为测试用例主方法的第一行并运行该程序。

Logger.getLogger("").getHandlers(); //Force load root logger handlers.
Logger.getLogger("").removeHandler((Handler) null);

您将看到现在没有记录任何记录器消息。如果您好奇为什么会这样,您可以阅读 java.util.logging.LogManager$RootLogger 源代码以了解详细信息。

您需要做的是创建一个 StreamHandler使用重定向的 System.err 流,然后 addremove来自记录器的 StreamHandler。您还可以切换 parent handlers 的使用在您的记录器配置上以避免写入原始 System.err。

另一种可能的解决方案是查找所有 ConsoleHandler 实例。将其全部删除并关闭。执行重新映射 System.err。然后创建并附加新的 ConsoleHandler。

JDK 方面,ConsoleHandler 和 ErrorManager 应该设计为使用 java.io.FileDescriptor永远不会重定向。

关于java - System.setErr() 干扰 Logger,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21417616/

相关文章:

java - Realm :迭代 RealmObject 并清除 ArrayList 字段

java - 使用 Netbeans 将数据插入 Access 时出错

java - GSon是否弄乱了时间戳变量

java - 使直方图和星形图输出不正确

java - 在 java 应用程序中将 css 包含到 jsp 的问题

java - 将 JUL 级别映射到 AppEngine Web 控制台级别

java - 如何将 AppEngine 请求日志发送到远程日志服务器?

java - Ehcache日志级别

java - 使用 apache commons-configuration PropertiesConfiguration 配置 java.util.logging?

java - Logger.getGlobal() 和 Logger.getAnonymousLogger() 之间的区别?