2017-04-21 96 views
3

我想以编程方式配置我的java.util.logging.Logger。根据Oracle Docs,似乎有可能。以编程方式配置记录器

但是这个例子说明什么是错在这里:

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)并创建一个新的(默认)记录器。为了“解决”这个问题,我可以在某个地方举一个特定记录器的引用,但我认为这不是一个好主意。

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

回答

2

为了“解决”这个问题,我可以在某个地方举一个特定记录器的引用,但我认为这不是一个好主意。

JDK6u18之前的版本中,LogManager对记录器持有强烈的参考。这个补丁之后,java.util.logging.Logger.getLogger()方法指向读者向持有很强的借鉴意义:

注:日志管理可以只保留弱引用到新创建的Logger。重要的是要明白,如果没有对记录器的强引用,那么以前创建的具有给定名称的记录器可能会随时被垃圾收集。特别是,这意味着如果没有对其他地方名为“MyLogger”的记录器的强引用,那么诸如getLogger(“MyLogger”).log(...)的两个背靠背调用可能会使用不同的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:潜在的丢失记录器变化,由于弱引用NCE中的OpenJDK(LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE)

+0

花了我一秒钟才明白为什么我从未遇到OP的问题。这绝对是你应该使用的成语。 – Qix

0

用于记录仪#getLogger的Javadoc引用您的问题:

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

注:日志管理可以只保留弱引用到新创建的Logger。重要的是要明白,如果没有对记录器的强引用,那么以前创建的具有给定名称的记录器可能会随时被垃圾收集。特别是,这意味着如果没有对其他地方名为“MyLogger”的记录器的强引用,那么诸如getLogger(“MyLogger”).log(...)的两个背靠背调用可能会使用不同的Logger对象,名为“MyLogger”在节目中。

反过来记录仪#getLogger调用日志管理#addLogger及其文档还鼓励你抱着一个参考:

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

应用程序应该保留自己的参考Logger对象,以避免它被垃圾收集。 LogManager只能保留一个弱引用。

相关问题