According to the JVM spec, the class loader that initiates loading of a class is recorded as the initiating class loader by the JVM. Furthermore, according to the JavaDoc of ClassLoader#findLoadedClass() the method
Returns the class with the given binary name if this loader has been recorded by the Java virtual machine as an initiating loader of a class with that binary name.
(emphasis mine)
Consider a simple class loader
class SimpleClassLoader extends ClassLoader {
void foo() {
System.err.println(loadClass("foo.Bar"));
System.err.println(findLoadedClass("foo.Bar"));
}
}
Given that foo.Bar
actually exists in the class path, new SimpleClassLoader().foo()
prints
class foo.Bar
null
According to the reasons given above, SimpleClassLoader
should be the initiating class loader and findLoadedClass("foo.Bar")
should just return the successfully loaded class.
Now consider this second version:
class SimpleClassLoader2 extends ClassLoader {
SimpleClassLoader2() {
super(null); // disables delegation
}
protected Class<?> findClass(String name) {
try {
byte[] b = IOUtils.toByteArray(new FileInputStream("path/to/foo/Bar.class"));
return defineClass("foo.Bar", b, 0, b.length);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
void foo() {
System.err.println(loadClass("foo.Bar"));
System.err.println(findLoadedClass("foo.Bar"));
}
}
This makes SimpleClassLoader2
both the initiating as well as the defining class loader of foo.Bar
. Indeed, now new SimpleClassLoader2().foo()
prints the desired
class foo.Bar
class foo.Bar
So either the documentation is wrong or I don't understand why SimpleClassLoader
is not regarded as the initiating class loader of foo.Bar
. Can someone please shed some light into this?