java.util.logging.Handler生命周期如何工作?

时间:2017-10-25 12:10:00

标签: java java.util.logging

我正在尝试实现一个自定义处理程序,将解析后的LogRecord个对象记录到一个文件中(基本上是FileHandlerStreamHandler所做的)。我目前的实施如下所示:

public final class ErrorHandler extends Handler {

private static final String OUTPUT_FILE = ".output";

private final Formatter formatter = new CustomFormatter();
private BufferedWriter writter;

@Override
public void publish(LogRecord record) {
    if (record.getLevel() == SEVERE || record.getLevel() == WARNING) {
        writeToOutput(record);
    }
}

void writeToOutput(LogRecord log) {
    try {
        if (writter == null) {
            writter = new BufferedWriter(new FileWriter(OUTPUT_FILE, true));
        }
        writter.write(formatter.format(log));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public void flush() {
}

@Override
public void close() {
    try {
        writter.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
}

PS:我知道我们可以通过在FileHandlerStreamHandler上设置过滤器和格式化程序来实现与上面的代码相同的功能,但是我将来会需要使用挂钩点

我的问题是,如果我在没有实现的情况下离开flush(),虽然创建了输出文件但是没有写入日志。如果我在writter.flush()内调用flush(),则会重复日志。虽然这可能发生了什么?

2 个答案:

答案 0 :(得分:0)

  

我的问题是,如果我没有实现执行flush(),虽然创建了输出文件,但是没有写入日志。

这是因为字节缓存在BufferedWriter中。 Flush将这些字节发送到包装的FileWriter。如果你收集到足够的字节,它将刷新到目标文件,但你可能会失去你的某些进程崩溃或磁盘问题的信息。

  

如果我在flush()中调用writter.flush(),则会重复日志。虽然这可能发生了什么?

也许您已将此处理程序的两个实例添加到记录器,并且两者都附加到同一文件。 Logger.addHandler的工作方式与List类似,而不像Set。将代码添加到Print the logger tree,它将告诉您安装了多少个处理程序实例。

  

我确定没有进程崩溃或磁盘问题,我相信close close会刷新。然而,我不知道为什么没有记录任何内容 - 而且只有文件尚未创建。

只有当Java virtual machine shuts down和处理程序在LogManager中可见时,才会隐式调用

Close。如果文档中描述的关闭不干净,则不会刷新缓冲的写入程序的内容。

答案 1 :(得分:0)

好的,经过两天的战斗,我开始意识到进程正在一个守护进程上运行,因此,处理程序的close()仅在守护程序被杀死时被调用。我相信这几乎同时导致多次调用flush()。没有守护进程运行进程解决了这个问题。