以编程方式配置Logger

时间:2017-04-21 11:23:10

标签: java java.util.logging

我想以编程方式配置java.util.logging.Logger。根据{{​​3}},似乎有可能。

但是这个例子显示了一些错误:

public static void main(String[] args) {
    Logger logger = Logger.getLogger("org.acme.project");
    logger.setLevel(Level.SEVERE);
    logger = null;

    System.gc();

    logger = Logger.getLogger("org.acme.project");
    logger.warning("You shouldn't see this warning!");
    logger.severe("But this error!");
}

如果您运行代码,则会看到这两条消息。但是,如果您删除logger = null;System.gc();,您只会看到正确的第二个,这证明垃圾收集器只是删除配置的记录器而离开Logger.getLogger(String)并创建一个新的(默认)之一。

To"解决"这个,我可以在某个地方引用那个特定的记录器,但我认为这不是一个好主意。

那么如何以编程方式定义记录器呢?

2 个答案:

答案 0 :(得分:2)

  

To"解决"这个,我可以在某个地方引用那个特定的记录器,但我认为这不是一个好主意。

JDK6u18之前的版本中,LogManager保留了对记录器的强引用。在该补丁之后,java.util.logging.Logger.getLogger()方法指向读者持有强大的参考:

  

注意:LogManager可能只保留对新创建的Logger的弱引用。重要的是要理解,如果没有对Logger的强引用,则可以随时对先前创建的具有给定名称的Logger进行垃圾收集。特别是,这意味着两个背靠背调用,如getLogger(" MyLogger")。log(...)可能会使用名为" MyLogger"的不同Logger对象。如果没有对名为" MyLogger"的记录器的强引用该计划的其他地方。

常用的习惯用法是:

private static final String CLASS_NAME = Foo.class.getName();
private static final Logger logger = Logger.getLogger(CLASS_NAME);

您定义CLASS_NAME的原因是您将其用于日志跟踪方法或logp方法

此外,像FindBugs这样的工具会将这种丢失的记录器模式检测为:

  LG:由于OpenJDK中的弱引用(LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE),可能导致记录器丢失;

答案 1 :(得分:0)

Javadoc for Logger#getLogger引用了您的问题:

https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html#getLogger%28java.lang.String%29

  

注意:LogManager可能只保留对新创建的Logger的弱引用。重要的是要理解,如果没有对Logger的强引用,则可以随时对先前创建的具有给定名称的Logger进行垃圾收集。特别是,这意味着两个背靠背调用,如getLogger(“MyLogger”)。log(...)可能使用名为“MyLogger”的不同Logger对象,如果没有对名为“MyLogger”的Logger的强引用在该计划中。

反过来Logger#getLogger调用LogManager#addLogger,它的文档也鼓励你持有一个参考:

https://docs.oracle.com/javase/7/docs/api/java/util/logging/LogManager.html#addLogger%28java.util.logging.Logger%29

  

应用程序应保留自己对Logger对象的引用,以避免被垃圾回收。 LogManager可能只保留弱引用。