Reputation: 4103
I want to configure my java.util.logging.Logger
programmatically. According to the Oracle Docs, it seems possible.
However this example shows something is wrong here:
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!");
}
If you run the code, you'll see both messages. However if you remove logger = null;
or System.gc();
you'll only see the correct second one, which proves the garbage collector just removes the configured logger leaving Logger.getLogger(String)
with creating a new (default) one.
To "solve" this, I could just hold a reference to that particular logger somewhere, but I don't think that's a good idea.
So how do I define a logger programmatically?
Upvotes: 4
Views: 2089
Reputation: 11035
To "solve" this, I could just hold a reference to that particular logger somewhere, but I don't think that's a good idea.
In releases prior to JDK6u18 the LogManager held strong reference to the logger. After that patch, the java.util.logging.Logger.getLogger() method points the reader towards holding a strong reference:
Note: The LogManager may only retain a weak reference to the newly created Logger. It is important to understand that a previously created Logger with the given name may be garbage collected at any time if there is no strong reference to the Logger. In particular, this means that two back-to-back calls like getLogger("MyLogger").log(...) may use different Logger objects named "MyLogger" if there is no strong reference to the Logger named "MyLogger" elsewhere in the program.
A common idiom is to use:
private static final String CLASS_NAME = Foo.class.getName();
private static final Logger logger = Logger.getLogger(CLASS_NAME);
The reason you define the CLASS_NAME
too is that you'll use it for the log tracing methods or the logp
methods
Also, tools like FindBugs will detect this lost logger pattern as:
LG: Potential lost logger changes due to weak reference in OpenJDK (LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE)
Upvotes: 2
Reputation: 6577
The Javadoc for Logger#getLogger references your problem:
Note: The LogManager may only retain a weak reference to the newly created Logger. It is important to understand that a previously created Logger with the given name may be garbage collected at any time if there is no strong reference to the Logger. In particular, this means that two back-to-back calls like getLogger("MyLogger").log(...) may use different Logger objects named "MyLogger" if there is no strong reference to the Logger named "MyLogger" elsewhere in the program.
In turn Logger#getLogger calls LogManager#addLogger and its documentation also encourages you to hold a reference:
The application should retain its own reference to the Logger object to avoid it being garbage collected. The LogManager may only retain a weak reference.
Upvotes: 1