按照Classloader的说法:不同的Classloader加载的类是不能相互访问的。先看一个例子:
public class Test{
public static void main(){
MyClassLoader cl = new MyClassLoader();
Class c = classloader.loadClass("A");
Object o = c.newInstance();
Method m = c.getMethod("run");
m.invoke(o);}
}
public class People{
public void run(){
System.out.println(Main.class.getClassLoader());
}
}public class MyClassLoader extends ClassLoader{
................................
public Class loadClass(String name) throws ClassNotFoundException{
System.out.println("try to load class " + name);
if("People".equals(name)){
return getSystemClassLoader().loadClass(name);
}
return loadClass(name, false);
}
public Class loadClass(String name, boolean resolve)throws ClassNotFoundException{
String filepathName = name.replace('.', '/');
//find class from current directory
byte[] b = read(new File(filepathName + ".class"));
Class clazz = defineClass(name, b, 0, b.length);
if(resolve){
resolveClass(clazz);
}
if(clazz == null){
throw new ClassNotFoundException("conld not find class " + clazz);
}
return clazz;
}}
运行输出如下:
try to load class People //只有这一个类是使用MyClassLoader加载的,其他的都委派给systemClassLoader了
try to load class java.lang.Object //因为People是MyClassLoader加载的,所以它依赖的类也会尝试用MyClassLoader加载
try to load class java.lang.System
try to load class java.io.PrintStream
try to load class Main
try to load class java.lang.Class
sun.misc.Launcher$AppClassLoader@1a5ab41
我所不明白的是:Object、System等类都是BootstrapClassLoader加载的,Main是AppClassLoader加载的,People是MyClassLoader加载的,如果按照不同的ClassLoader加载的类不能相互访问,那么这里的People是如何访问Object System Main的呢?
问题补充
终于能上网了,爽啊!
ClassLoader的parent并不是它继承的类,而是它的parent属性。ClassLoader类的loadClass实现:
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// First, check if the class has already been loaded
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
假设我自己定义的MyClassLoader也遵循双亲委托机制(我只定义findClass方法),foo.SomeClass是由parent载入的,假设这个parent就是AppClassLoader,调用foo.SomeClass.getClassLoader(),返回的是AppClassLoader,跟我的MyClassLoader一点关系都没有,bar.SomeClass是MyClassLoader加载的,为什么它能访问MyClassLoader呢?我猜想JVM里,除了保存类的ClassLoader,还保存了相关的ClassLoader。
如果bar.someClass是MyClassLoader加载的,它有这样的代码:
foo.SomeClass a = new foo.SomeClass()
即使AppClassLoader已经加载过foo.SomeClass(),bar.someClass并不会使用已经存在的foo.someClass,而是请求MyClassLoader来加载bar.someClass,这时候就建立了MyClassLoader和foo.someClass的联系。
可惜我的《深入Java虚拟机》找不到了,里面不知道有没有提到点这方面的东西,google了很久也没效果。