Thread.currentThread().getContextClassLoader().loadClass(className); 和 Class.forName(className);有什么区别呀,他们的底层不都是调用了ClassLoader.getCallerClassLoader()来得到loader的吗?

解决方案 »

  1.   

    哥们这根本不是同一个东东,,Thread.currentThread().getContextClassLoader().loadClass(className);这应该是多线程中的,,Class.forName(className);这个应该是你在加载驱动,而是当前的类....
      

  2.   

    是啊!
    Thread.currentThread().getContextClassLoader().loadClass(className);
    中获取到的ClassLoader不一定和Class.forname()中用的ClassLoader一致啊,因为Thread可以通过setContextClassLoader设置classLoader的啊。也就是说我完全可以为当前运行的线程设置一个我自定义的ClassLoader.
      

  3.   

    以前翻译过的一篇文章,也许对你有点用吧,记得给分噢!Find a way out of ClassLoader maze
    - By gloomyfish
    尽管不常被问到,但是这种问题要正确的回答还是很困难的。它通常出现在框架编程期间,
    当要处理一个动态类和资源加载的时候。总的说来,当动态地加载资源的时候,你至少有三
    种类加载器可以选择:系统类加载器(也指应用程序)、当前类加载器(the current classloader)
    当前线程环境类加载器(the current thread context classloader)。上面的问题参考下面,哪个
    类加载器是正确的选择。第一个容易被排除选择是:系统类加载器(system classloader)。类加载器处理-classpath下的
    目录而且是可以编程访问像这样:ClassLoader.getSystemClassLoader()。所有的
    ClassLoader.getSystemXXX() API方法都可以通过这个类加载器来路由。你应该少
    写代码来显式的用上面的任何方法,相反地要让其它地类加载器代理系统类加载器。否则你
    的代码只能是工作在命令行方式下的应用,当系统类加载器是最后被JVMC创建时候。只要
    你移植你的代码到企业级javabean/ web application/ java web start
    Application事情将肯定出错的。因此,现在我们只剩下两个选择:当前的类加载器和上下文环境类加载器。由定义看,当前
    类加载器加载和定义的类是你当前方法属于的。这个类加载器暗示在运行时动态关联的类之
    间分解,当你用一个参数版本的相似方法Class.forName(), Class.getResource()。
    它也被用来构造语法像X.class这样的类描述。线程环境上下文类加载器在JAVA2 标准种被介绍进来,每个线程有上下文类加载器与之关
    联。它可以被设定通过Thread.setContextClassLoader()方法,如果你在线程构造
    之后没有调用这个方法,线程将会继承它的context ClassLoader从它的父线程。如果
    你什么都没有做在整个应用程序中,所有的线程最终以系统类加载器作为它们的context ClassLoader。理解这点非常重要,很少有这样的情况出现因为WEB 和JAVA 2 企业应
    用服务器采用更加世故的类加载器分层为了不同的特征如:JNDI、线程池、组件热部署等。为什么线程上下文类加载器会在第一个地方呢?它们被悄悄地介绍进了J2SE体系中,缺少
    来自SUN官方正确的指导和文档帮助,这个也是很对开发者对此感到困惑的原因。事实上,context ClassLoader提供一个后门为类加载委派策略也被介绍进J2SE
    中来。(原文是这样:In truth, context classloaders provide a back door
     around the classloading delegation scheme also introduced in J2SE.)
    正常地,JVM中所有的类加载器被按层次组织这样每个类加载器都有唯一的父类加载器(除
    了启动整个JVM的原始类加载器),当请求加载一个类的时候,每个类加载器的顺序是首先希望委派加载给它的父类,只有当父类加载器失败以后它才尝试自己定义这个类。有些情况下,这种顺序的安排不起作用,尤其当JVM核心代码必须动态加载有应用程序开发者提供的资源时候。考虑JNDI的例子,在rt.jar中它的内容有启动类完成,但是这些
    核心的JNDI类加载JNDI提供者有独立开发商或者被应用程序以-classpath潜在部署。
    这种情况下调用一个父类加载器去加载一个对它的子类加载器来说是可以见到的类,正常的
    J2SE委派策略将不再工作。工作区是使核心JNDI类用线程上下文环境类加载器,有效的
    隧道穿过类加载器层次在与正常委派相反的方向上。
    顺便说一下,前面一节可能已经提醒你一些其它的事情:JAVA API FOR XML PARSE(JAXP)。是的,当JAXP只是J2SE的一个扩展的时候,XML解析器工厂用当前类加载器
    方法启动解析器完成。当JAXP成为J2SE 1.4的核心部分的时候,类加载变成了用线程
    上下文环境加载器,完全的类似于JNDI。明白我说缺少SUN的文档指导的意思了吧!在这些介绍之后,我们靠近了问题的结症所在,剩下的两种选择没有一个是在所有情况都下都是正确的。一些人相信线程上下文环境类加载器应该成为一个新的标准战略。它会创建一
    个非常乱的加载关系图假如不同的JVM线程要处理同一个共享数据区,除非它们都使用相
    同的上下文加载器实例。而且,委派到当前类加载器已经是一个合法的规则在一些已经存在
    的情况中像类语法,显式调用Class.forName()。即使你做出了额外的努力无论什么情
    况下你都用context ClassLoader,总有一些代码不在你的控制之中而委派到当前加载
    器。这种不受控制的混合委派策略听起来相当的危险。更糟糕的问题是,某个应用程序设定上下文和当前的类加载器成不同的类加载器实例,有同
    样的类类路径不同的委派双亲和孩子。花几秒钟想想为什么这个特别可怕。记得类加载器加
    载和定义一个类是JVM ID的一部分。如果当前的类加载器加载一个类X然后执行它,说,
    一个JNDI查找类型为Y的数据,上下文加载器(context ClassLoader)能加载和定
    义Y。这个Y定义不同于相同的名字被当前类加载器看到的。遇到这种模糊的类转型,加载
    器将会抛出强制异常。这种混乱可能一直存在一段时间,用J2SE API 来动态加载任何资源都要去尽力猜出是用哪种加载策略。这里是一个例子: JNDI 用context ClassLoader
     Class.getResource() 和 Class.forName() 用current ClassLoader
     JAXP 用context ClassLoader
     Java.util.ResourceBundle 用调用者的 current classLoader
     URL protocol handles specified via java.protocol.hander.pkgs 在启动时候查找系统属性,所以只能用system ClassLoader
     JAVA串行化API用调用者当前加载器,默认情况下!
      

  4.   

    Thread.currentThread().getContextClassLoader().loadClass(className);First, check if the class has already been loaded。