Which class loader should be recorded as initiating loader?

ravenex ravenex at qq.com
Sat Oct 15 06:18:17 PDT 2011


Hi all,
  
 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]:
 But it looks like that's an incorrect impression.
  
 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.
  
 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.
 I've tried writing an actual code to emulate the example, and on JDK6, it shows the description in [1] is wrong.
  
 -----------------------------------------------
 TestInitiatingLoader.java
  
 import java.io.*;
import java.net.*;
  
 public class TestInitiatingLoader {
  public static void main(String[] args) throws Exception {
    Grandma grandma = new Grandma();
    Mom mom = new Mom(grandma);
    Cindy cindy = new Cindy(mom);
    cindy.loadClass("Dummy").newInstance(); // force class init
    
    final String reader = "java.io.FileReader";
    printStats(grandma, reader); // false
    printStats(mom, reader);     // false
    printStats(cindy, reader);   // true
  }
  
  private static void printStats(LoadedClassQueryable loader, String name) {
    System.out.printf("Is %s an initiating loader of %s: %b\n",
      loader.getClass().getName(),
      name,
      loader.foundLoadedClass(name));
  }
}
  
 interface LoadedClassQueryable {
  boolean foundLoadedClass(String name);
}
  
 class Cindy
    extends URLClassLoader
    implements LoadedClassQueryable {
  public Cindy(ClassLoader parent) {
    super(makeArgs(), parent);
  }
  
  private static URL[] makeArgs() {
    try {
      return new URL[] { new File(".").toURI().toURL() };
    } catch (Exception e) {
      e.printStackTrace();
      return new URL[] { };
    }
  }
  
  @Override
  public Class<?> loadClass(String name) throws ClassNotFoundException {
    if ("Dummy".equals(name)) {
      // force Cindy to load this Dummy class
      return findClass("Dummy");
    }
    return super.loadClass(name);
  }
  
  @Override
  public boolean foundLoadedClass(String name) {
    return findLoadedClass(name) != null;
  }
}
  
 class Mom
    extends ClassLoader
    implements LoadedClassQueryable {
  public Mom(ClassLoader parent) {
    super(parent);
  }
  
  @Override
  public boolean foundLoadedClass(String name) {
    return findLoadedClass(name) != null;
  }
}
  
 // use system class loader as parent
class Grandma
    extends ClassLoader
    implements LoadedClassQueryable {
  @Override
  public boolean foundLoadedClass(String name) {
    return findLoadedClass(name) != null;
  }
}
-----------------------------------------------
 Dummy.java
  
 import java.io.*;
  
 public class Dummy {
  static {
    // Dummy should be loaded by Cindy.
    // So Cindy will be recorded as an initiating loader for java.io.FileReader
    try {
      new FileReader("Dummy.class").close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
-----------------------------------------------
  
 Could anybody clarify which loaders are supposed to be recorded as an initiating loader?
  
 [1]: http://www.artima.com/insidejvm/ed2/linkmod3.html
 [2]: http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html#79441
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/jdk6-dev/attachments/20111015/ec794216/attachment.html 


More information about the jdk6-dev mailing list