-
Bug
-
Resolution: Unresolved
-
P4
-
6
-
None
-
generic
-
generic
In LogManager.java in the static initializer it does some class loader lookups.
It uses the system class loader first, then uses the context class loader.
It should be sufficient to allow the context class loader to delegate
to the system class loader in the normal manner, only falling back
to explicit use of the system class loader if the context class loader
fails to load the class.
Better yet, it should probably use the technique we describe in the
Java EE 6 platform spec (although I'm not sure the AccessController
stuff is required in this context):
Libraries that dynamically load classes must consider the class loading
environment of a Java EE application. Libraries will often be loaded by
a class loader that is a parent class loader of the class loader that
is used to load application classes. A library that only needs to
dynamically load classes provided by the library itself can safely use
the Class method forName. However, libraries that need to dynamically
load classes that have been provided as a part of the application need
to use the context class loader to load the classes. Access to the
context class loader requires RuntimePermission(“getClassLoader”),
which is not normally granted to applications, but should be granted to
libraries that need to dynamically load classes. Libraries can use a
method such as the following to assert their privilege when accessing
the context class loader. This technique will work in both Java SE and
Java EE.
public ClassLoader getContextClassLoader() {
return AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
} catch (SecurityException ex) { }
return cl;
}
});
}
Libraries should then use the following technique to load classes.
ClassLoader cl = getContextClassLoader();
if (cl != null) {
try {
clazz = Class.forName(name, false, cl);
} catch (ClassNotFoundException ex) {
clazz = Class.forName(name);
}
} else
clazz = Class.forName(name);
It uses the system class loader first, then uses the context class loader.
It should be sufficient to allow the context class loader to delegate
to the system class loader in the normal manner, only falling back
to explicit use of the system class loader if the context class loader
fails to load the class.
Better yet, it should probably use the technique we describe in the
Java EE 6 platform spec (although I'm not sure the AccessController
stuff is required in this context):
Libraries that dynamically load classes must consider the class loading
environment of a Java EE application. Libraries will often be loaded by
a class loader that is a parent class loader of the class loader that
is used to load application classes. A library that only needs to
dynamically load classes provided by the library itself can safely use
the Class method forName. However, libraries that need to dynamically
load classes that have been provided as a part of the application need
to use the context class loader to load the classes. Access to the
context class loader requires RuntimePermission(“getClassLoader”),
which is not normally granted to applications, but should be granted to
libraries that need to dynamically load classes. Libraries can use a
method such as the following to assert their privilege when accessing
the context class loader. This technique will work in both Java SE and
Java EE.
public ClassLoader getContextClassLoader() {
return AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
ClassLoader cl = null;
try {
cl = Thread.currentThread().getContextClassLoader();
} catch (SecurityException ex) { }
return cl;
}
});
}
Libraries should then use the following technique to load classes.
ClassLoader cl = getContextClassLoader();
if (cl != null) {
try {
clazz = Class.forName(name, false, cl);
} catch (ClassNotFoundException ex) {
clazz = Class.forName(name);
}
} else
clazz = Class.forName(name);