[英]System.setErr() interferes with Logger
在一个更大的程序中,我使用静态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正在写入一个封闭的流。
要证明这一点,请将以下内容添加为测试用例main方法的第一行并运行该程序。
Logger.getLogger("").getHandlers(); //Force load root logger handlers.
Logger.getLogger("").removeHandler((Handler) null);
您将看到现在没有记录任何记录器消息。 如果您很好奇为什么会这样,您可以阅读java.util.logging.LogManager$RootLogger
源代码以获取详细信息。
您需要做的是使用重定向的System.err流创建StreamHandler ,然后从记录器中添加和删除 StreamHandler。 您还可以在记录器配置上切换父处理程序的使用,以避免写入原始System.err。
另一种可能的解决方案是找到所有ConsoleHandler实例。 删除并关闭所有这些。 执行重映射System.err。 然后创建并附加新的ConsoleHandler。
JDK明智的,ConsoleHandler和ErrorManager应该被设计为使用从未重定向的java.io.FileDescriptor 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.