jiangtaigong 2009-10-01 21:08
浏览 202
已采纳

关于ClassLoader的一点疑惑

按照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了很久也没效果。
  • 写回答

4条回答 默认 最新

  • ningmenglovesoft 2009-10-01 21:08
    关注

    子加载器在加载类之前会先委托父加载器先进行加载。这也就是类加载器父委托机制。但是父加载器不能委托子加载器进行加载,所以people是可以访问到父加载器加载的类。而父加载器加载的类。不能访问到子加载器加载的类。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥50 易语言把MYSQL数据库中的数据添加至组合框
  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况