You have to pin your loggers in memory or setup a logging.properties
config file. From the java.util.logging.Logger docs:
Logger objects may be obtained by calls on one of the getLogger factory methods. These will either create a new Logger or return a suitable existing Logger. It is important to note that the Logger returned by one of the getLogger factory methods may be garbage collected at any time if a strong reference to the Logger is not kept.
When a new logger is returned the log level is determined by the LogManager which by default uses settings from a logging.properties
file. In your example, it is possible to see the following:
- Call to getLogger creates a new logger and sets level from LogManager.
- Your code sets the logger level to OFF.
- G.C. runs and destroys your logger along with settings you just applied.
- Selenium calls getLogger and creates a new logger and sets level from LogManager.
Here is an example test case to prove the point:
public static void main(String[] args) {
String name = "com.gargoylesoftware.htmlunit";
for (int i = 0; i < 5; i++) {
System.out.println(Logger.getLogger(name).getLevel());
Logger.getLogger(name).setLevel(Level.OFF);
System.runFinalization();
System.gc();
System.runFinalization();
Thread.yield();
}
}
Which will output null
instead of OFF
.
If you pin your logger by holding a strong reference then step #3 never happens and Selenium should instead find the logger you created which has the level set to OFF.
private static final Logger[] pin;
static {
pin = new Logger[]{
Logger.getLogger("com.gargoylesoftware.htmlunit"),
Logger.getLogger("org.apache.commons.httpclient"),
Logger.getLogger("org.openqa.selenium.remote.ProtocolHandshake")
};
for (Logger l : pin) {
l.setLevel(Level.OFF);
}
}