<DIV>Hi all,</DIV>
<DIV> </DIV>
<DIV>I've long had an impression that all class loaders in an loadClass() chain should be recorded as initiating loaders. That knowledge comes from Inside the Java Virtual Machine, 2nd Edition [1]:</DIV>
<DIV>But it looks like that's an incorrect impression.</DIV>
<DIV> </DIV>
<DIV>According to the JVMS2e 5.3.2 [2], the "Otherwise" paragraph, only when the JVM initiates a class loading process, the loader directly invoked by the JVM will be recorded as the initiating loader; the ones in the middle of the delegation chain won't be recorded. A loader whose loadClass() is called explicitly (and successfully completed) from Java code isn't necessarily recorded as an initiating loader.</DIV>
<DIV> </DIV>
<DIV>Using the example in [1] in the "Now imagine" paragraph, only Cindy should be an initiating loader of java.io.FileReader; neither Mom nor Grandma should be recorded as an initiating loader.</DIV>
<DIV>I've tried writing an actual code to emulate the example, and on JDK6, it shows the description in [1] is wrong.</DIV>
<DIV> </DIV>
<DIV>-----------------------------------------------</DIV>
<DIV>TestInitiatingLoader.java</DIV>
<DIV> </DIV>
<DIV>import java.io.*;<BR>import java.net.*;</DIV>
<DIV> </DIV>
<DIV>public class TestInitiatingLoader {<BR> public static void main(String[] args) throws Exception {<BR> Grandma grandma = new Grandma();<BR> Mom mom = new Mom(grandma);<BR> Cindy cindy = new Cindy(mom);<BR> cindy.loadClass("Dummy").newInstance(); // force class init<BR> <BR> final String reader = "java.io.FileReader";<BR> printStats(grandma, reader); // false<BR> printStats(mom, reader); // false<BR> printStats(cindy, reader); // true<BR> }<BR> <BR> private static void printStats(LoadedClassQueryable loader, String name) {<BR> System.out.printf("Is %s an initiating loader of %s: %b\n",<BR> loader.getClass().getName(),<BR> name,<BR> loader.foundLoadedClass(name));<BR> }<BR>}</DIV>
<DIV> </DIV>
<DIV>interface LoadedClassQueryable {<BR> boolean foundLoadedClass(String name);<BR>}</DIV>
<DIV> </DIV>
<DIV>class Cindy<BR> extends URLClassLoader<BR> implements LoadedClassQueryable {<BR> public Cindy(ClassLoader parent) {<BR> super(makeArgs(), parent);<BR> }<BR> <BR> private static URL[] makeArgs() {<BR> try {<BR> return new URL[] { new File(".").toURI().toURL() };<BR> } catch (Exception e) {<BR> e.printStackTrace();<BR> return new URL[] { };<BR> }<BR> }<BR> <BR> @Override<BR> public Class<?> loadClass(String name) throws ClassNotFoundException {<BR> if ("Dummy".equals(name)) {<BR> // force Cindy to load this Dummy class<BR> return findClass("Dummy");<BR> }<BR> return super.loadClass(name);<BR> }<BR> <BR> @Override<BR> public boolean foundLoadedClass(String name) {<BR> return findLoadedClass(name) != null;<BR> }<BR>}</DIV>
<DIV> </DIV>
<DIV>class Mom<BR> extends ClassLoader<BR> implements LoadedClassQueryable {<BR> public Mom(ClassLoader parent) {<BR> super(parent);<BR> }<BR> <BR> @Override<BR> public boolean foundLoadedClass(String name) {<BR> return findLoadedClass(name) != null;<BR> }<BR>}</DIV>
<DIV> </DIV>
<DIV>// use system class loader as parent<BR>class Grandma<BR> extends ClassLoader<BR> implements LoadedClassQueryable {<BR> @Override<BR> public boolean foundLoadedClass(String name) {<BR> return findLoadedClass(name) != null;<BR> }<BR>}<BR>-----------------------------------------------</DIV>
<DIV>Dummy.java</DIV>
<DIV> </DIV>
<DIV>import java.io.*;</DIV>
<DIV> </DIV>
<DIV>public class Dummy {<BR> static {<BR> // Dummy should be loaded by Cindy.<BR> // So Cindy will be recorded as an initiating loader for java.io.FileReader<BR> try {<BR> new FileReader("Dummy.class").close();<BR> } catch (Exception e) {<BR> e.printStackTrace();<BR> }<BR> }<BR>}<BR>-----------------------------------------------</DIV>
<DIV> </DIV>
<DIV>Could anybody clarify which loaders are supposed to be recorded as an initiating loader?</DIV>
<DIV> </DIV>
<DIV>[1]: <A href="http://www.artima.com/insidejvm/ed2/linkmod3.html">http://www.artima.com/insidejvm/ed2/linkmod3.html</A></DIV>
<DIV>[2]: <A href="http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html#79441">http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html#79441</A></DIV>