我一直没有弄懂ContextClassLoader的意思,我在网上搜索了些资料,只是说可以改变传统类加载委托机制,也就是相当于违背类加载器的委托机制。我设计了如下的测试类,但是有问题。如下:测试思想:
Test1这个类放到classpath目录下,Test1中调用Test2类,Test2是放到jre/lib/ext目录下的,也就是ext类加载器来加载
Test2中调用Test3类,Test3是放在classpath类中的。因为Test2类是ExtClassLoader加载的,原理上Test2去加载Test3的时候应该是委托Ext加载器和Ext的父类加载器去加载,这个时候肯定加载不上,因为Test3是放到classpath目录下的,所以我想通过ContextClassLoader来改变这种委托关系,改变当前线程的类加载器,通过ClassLoader.getSystemClassLoader()来加载Test3.但是运行结果没有加载到。不知道是什么原因导致的?
package com.test;
//客户端类,这个类放在classpath下
public class Test1 {

public static void main(String[] args) {

System.out.println("test1 ClassLoader:"+Test1.class.getClassLoader());
Test2 ts = new Test2();
ts.test();
System.out.println("test1结束了。");
}
}
//下面是第二个类
package com.test;
import java.lang.reflect.Method;//这个类单独打成jar包,放到jre/lib/ext/目录下,也就是让ext类加载器来加载
public class Test2 { public void test(){
System.out.println("test2 的类加载器:"+this.getClass().getClassLoader());

ClassLoader cl = Thread.currentThread().getContextClassLoader();
System.out.println("系统类加载器:"+ClassLoader.getSystemClassLoader());
Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
try{
Class clas = Class.forName("com.test.Test3");
Object obj = clas.newInstance();
Method m = clas.getMethod("test", null);
m.invoke(obj, null);
}catch(Exception e){
e.printStackTrace();
}finally{
Thread.currentThread().setContextClassLoader(cl);
}
}
}//第三个类
package com.test;//第三个类放在classpath目录下
public class Test3 {
  
public void test(){
System.out.println("test3类加载器:"+this.getClass().getClassLoader());


}
}运行结果报找不到Test3这个类,如果按照ContextClassLoader的机制应该可以找到啊?因为我改变了当前线程上下文类加载器,将当前类加载器修改为了AppClassLoader,这个类加载器会找到classpath下的Test3才对啊,这里没有想明白,请大师们帮分析下哪里出错了。test1 ClassLoader:sun.misc.Launcher$AppClassLoader@82ba41
test2 的类加载器:sun.misc.Launcher$ExtClassLoader@923e30
系统类加载器:sun.misc.Launcher$AppClassLoader@82ba41
test1结束了。
java.lang.ClassNotFoundException: com.test.Test3
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:164)
at com.test.Test2.test(Test2.java:14)
at com.test.Test1.main(Test1.java:12)

解决方案 »

  1.   

    Class.forName只会用当前代码的classloader去加载参数所指定的类
      

  2.   


    那我用下面的代码也找不到Test3这个类,请问我该怎么写才能加载到Test3这个类呢?
    Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
    try{
                            Test3 t3 = new Test3();
                            t3.test();
    }catch(Exception e){
    e.printStackTrace();
    }finally{
    Thread.currentThread().setContextClassLoader(cl);
    }
      

  3.   

    你用下面这个试试
    Thread.currentThread().getContextClassLoader().loadClass(className);
      

  4.   

    Test.class.getClassLoader().loadClass(className)
    试试这种