读书人

哪位高手是initiating loader

发布时间: 2012-10-21 09:00:08 作者: rapoo

谁是initiating loader
《深入Java虚拟机》第二版(很老的那本,Bill Venners写的,有中文翻译那本)第八章讲解类加载器用了个Cindy、Mom、Grandma的例子。但那个例子是错的。发了邮件到jdk6-dev邮件列表,等待答复。顺便发这边大家讨论。

那个例子说,Cindy的parent是Mom,Mom的parent是Grandma,Grandma的parent是null也就是bootstrap class loader。
Cindy尝试加载java.io.FileReader会委派给Mom,Mom委派给Grandma,Grandma委派给bootstrap,bootstrap成功加载并一层层把Class返回出来。
这个过程完成后,书上说Cindy、Mom、Grandma都应该是initiating loader。但事实却不是如此。

代码例子:

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;  }}class Grandma    extends ClassLoader    implements LoadedClassQueryable {  public Grandma() {    super(null); // use bootstrap class loader as parent  }    @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();    }  }}


运行结果:
Is Grandma an initiating loader of java.io.FileReader: falseIs Mom an initiating loader of java.io.FileReader: falseIs Cindy an initiating loader of java.io.FileReader: true


ClassLoader.findLoadedClass()可用于确认一个类与initiating loader关系。
public Class<?> loadClass(String name) throws ClassNotFoundException { if ("Dummy".equals(name)) { // force Cindy to load this Dummy class return findClass("Dummy"); } return getParent().loadClass(name); }

读书人网 >编程

热点推荐