我想通过编程方式配置我的 java.util.logging.Logger
。根据Oracle文档,似乎有可能。
但是,此示例在这里显示出什么问题:
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)
留下创建新的(默认(一个。
要"解决"这个问题,我可以在某个地方提及该特定的记录器,但我认为这不是一个好主意。
那么我如何以编程方式定义记录器?
要"解决"这个问题,我可以在某个地方提及该特定的记录器,但我认为这不是一个好主意。
在JDK6U18之前发行版中,Logmanager对Logger有很强的引用。在该补丁之后,Java.util.logging.logger.getLogger((方法将读者指向有很强的参考:
注意:Logmanager只能保留对新创建的Logger的弱参考。重要的是要了解,如果没有强烈的对记录器的参考,则可以随时收集具有给定名称的先前创建的记录器。特别是,这意味着两个背对背调用,例如getLogger(" mylogger"(。log(...(可能会使用名为" mylogger"的不同的记录器对象,如果对其他位置的名为" mylogger"的logger没有强烈的引用在程序中。
一个常见的成语是使用:
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_to_weak_reference(
logger#getlogger引用您的问题:
在注意:Logmanager只能保留对新创建的Logger的弱参考。重要的是要了解,如果没有强烈的对记录器的参考,则可以随时收集具有给定名称的先前创建的记录器。特别是,这意味着两个背对背调用,例如getLogger(" mylogger"(。log(...(可能会使用名为" mylogger"的不同的记录器对象,如果对其他位置的名为" mylogger"的logger没有强烈的引用在程序中。
反过来logger#getlogger调用logmanager#addlogger及其文档也鼓励您保存参考:
https://docs.oracle.com/javase/7/docs/api/java/java/util/logging/logmanager.html#addlogger(java.util.util.util.logging.logger.logger;
该应用程序应保留自己对Logger对象的引用,以避免收集垃圾。logmanager只能保留弱参考。