I did some more tests, and I'm sure the spec is implemented correctly. My mistake was that the reflective loading of the class is the same as loading it as part of the resolution step. This makes sense: both the specification and the JavaDoc mention the "record" of the class loader as the starting class loader. If I call loadClass() myself, the VM has no way of knowing which classloader should be the initiating classloader, so the defining classloader also trivially becomes the classloader.
This can be demonstrated by loading a loaded class with a trigger of another class ( foo.Baz ) as part of resolving dependencies, but loading another class loader actually loads it. *
* I am sure that this is the wrong behavior of a valid class loader. I just do it to illustrate the point.
Consider the following classes (they are all in the foo package):
public class Bar { public Bar() { new Baz(); } }
and
public class Baz { }
My custom classloader is now slightly modified:
public class SimpleClassLoader extends ClassLoader { static final String PATH = "/path/to/classes"; public SimpleClassLoader() {
The test goes straight:
public static void main(String[] args) throws Exception { SimpleClassLoader cl = new SimpleClassLoader(); Class<?> cls = cl.loadClass("foo.Bar"); cls.newInstance();
Exit
findLoadedClass(foo.Bar) = class foo.Bar, has class loader foo.SimpleClassLoader@3a65724d findLoadedClass(foo.Baz) = class foo.Baz, has class loader sun.misc.Launcher$AppClassLoader@1a2b2cf8
As you can see: SimpleClassLoader initiates the download and also defines foo.Bar . Creating an instance triggers the foo.Baz permission. This time the class definition is delegated to the system class loader, so it becomes the defining class loader. The output shows that SimpleClassLoader launches the class loader for both classes, but only defines the first class.
musiKk
source share