JDK-6207335 : Handler loading fails for LogManager under Java Web Start (Classloader problem)
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util.logging
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Future Project
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2004-12-10
  • Updated: 2012-01-24
  • Resolved: 2005-05-02
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbd_majorResolved
Description
FULL PRODUCT VERSION :
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600] (but will occur under all OS's under Java Web Start

EXTRA RELEVANT SYSTEM CONFIGURATION :
Problem will happen for any situation where the handler to be loaded is not laoded with the System classloader. Most common situation is Java Web Start.

A DESCRIPTION OF THE PROBLEM :
This is related to bug 4931321 which was fixed for Tiger, but is different. java.util.logging.LogManager allows you to configure the global handlers through a configuration properties read from an input stream using readconfiguration(). This properties file can specify Handlers using the property "handlers".

The handlers are created using reflection in the private method initializeGlobalHandlers(). This instantiates them by doing:

Class clz = ClassLoader.getSystemClassLoader().loadClass(word);
Handler h = (Handler) clz.newInstance();

This will fail if the handler class is not a System class (a class loaded by the System classloader). A similar bug was reported for the LogManager property (bug id: 4931321) and was fixed for Tiger by changing the code to look like (in readConfiguration()):

try {
    Class clz = ClassLoader.getSystemClassLoader().loadClass(cname);
    clz.newInstance();
    return;
} catch (ClassNotFoundException ex) {
    Class clz = Thread.currentThread().getContextClassLoader().loadClass(cname);
    clz.newInstance();
    return;
}


 I believe a similar fix should be applied here, ie:

Class clz;
try {
  clz = ClassLoader.getSystemClassLoader().loadClass(word);
} catch (ClassNotFoundException ex) {
   clz = Thread.currentThread().getContextClassLoader().loadClass(word);
}
Handler h = (Handler) clz.newInstance();

It might be worth doing a global inspection for the method ClassLoader.getSystemClassLoader(), as the usages in getFilterProperty(), getFormatterProperty(), and 2 x addLogger()  look like they will fail under webstart too.





STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) Construct a class with extends Handler, eg com.xyz.FooHandler, and a main method that calls LogManager.readConfiguration() with a properties file that has the line "handlers = com.xyz.FooHandler"
3) compile the class, jar it up, sign etc, and start with Java Web Start
4) wait for an exception on the console


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect the handler to be added to the global handlers properly, and no messages on console

ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.ClassNotFoundException: com.xyz.FooHandler
java.lang.ClassNotFoundException: com.xyz.FooHandler
	at java.net.URLClassLoader$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at java.util.logging.LogManager$7.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.util.logging.LogManager.initializeGlobalHandlers(Unknown Source)
	at java.util.logging.LogManager.access$900(Unknown Source)
	at java.util.logging.LogManager$RootLogger.log(Unknown Source)
	at java.util.logging.Logger.doLog(Unknown Source)
	at java.util.logging.Logger.log(Unknown Source)
	at java.util.logging.Logger.warning(Unknown Source)
	at com.xyz.FooHandler.main(FooHandler.java:30)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at com.sun.javaws.Launcher.executeApplication(Unknown Source)
	at com.sun.javaws.Launcher.executeMainClass(Unknown Source)
	at com.sun.javaws.Launcher.continueLaunch(Unknown Source)
	at com.sun.javaws.Launcher.handleApplicationDesc(Unknown Source)
	at com.sun.javaws.Launcher.handleLaunchFile(Unknown Source)
	at com.sun.javaws.Launcher.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
ok


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package com.xyz;

import java.util.logging.*;

public class FooHandler extends Handler {
  public void publish(LogRecord record) {}
  public void flush() {}
  public void close() throws SecurityException {}

  public static void main(String [] args) {
    try {
      LogManager.getLogManager().readConfiguration(new StringBufferInputStream("handlers=com.modusfund.util.FooHandler"));
      LogManager.getLogManager().getLogger("").warning("test");
      System.out.println("ok");
    }catch(Exception ex) {
      ex.printStackTrace();
    }
  }
}


---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Configure the handlers manually, rather than via a configuration file.
LogManager.getLogManager().getLogger("").addHandler(new com.xyz.FooHandler())
###@###.### 2004-12-10 22:47:55 GMT