getClassLoader()和getContextClassLoader()的区别

 

   区别一: 

          getClassLoader()是当前类加载器,而getContextClassLoader是当前线程的类加载器

 

   区别二:

         getClassLoader是使用双亲委派模型来加载类的,而getContextClassLoader就是为了避开双亲委派模型的加载方式的,也就是说它不是用这种方式来加载类

当前类加载器加载和定义当前方法所属的那个类。这个类加载器在你使用带单个参数的Class.forName()方法,Class.getResource()方法和相似方法时会在运行时类的链接过程中被隐式调用(也就是说当你用Class.forname(package.className)的时候已经调用当前类加载器来加载这个类了)

转载个例子

     Thread context class loader存在的目的主要是为了解决parent delegation机制下无法干净的解决的问题。假如有下述委派链: 
    ClassLoader A -> System class loader -> Extension class loader -> Bootstrap class loader 

那么委派链左边的ClassLoader就可以很自然的使用右边的ClassLoader所加载的类。 

但如果情况要反过来,是右边的ClassLoader所加载的代码需要反过来去找委派链靠左边的ClassLoader去加载东西怎么办呢?没辙,parent delegation是单向的,没办法反过来从右边找左边。 

这种情况下就可以把某个位于委派链左边的ClassLoader设置为线程的context class loader,这样就给机会让代码不受parent delegation的委派方向的限制而加载到类了

 

 

有时这种加载顺序不能正常工作,通常发生在有些JVM核心代码必须动态加载由应用程序开发人员提供的资源时(比如说在核心类A中,它要动态加载一个应用程序开发人员提供的类B时,假如说类A是由扩展类加载器(Extension ClassLoader)加载的,根据双亲委派模型的要求,它会先把B交给它的父加载器也就是启动类加载器(Bootstrap ClassLoader),这时候启动类加载器(Bootstrap ClassLoader)加载不了,那扩展类加载器就会尝试自己加载,这时候它也加载不了,这就尴尬了,就会报ClassNotFoundException了)

 

以JNDI举例:它的核心内容在rt.jar中的引导类中实现了,但是这些JNDI核心类可能加载由独立厂商实现和部署在应用程序的classpath中的JNDI提供者。这个场景要求一个父类加载器(这个例子中的原始类加载器,即加载rt.jar的加载器)去加载一个在它的子类加载器(系统类加载器)中可见的类。此时通常的J2SE委托机制不能工作,解决办法是让JNDI核心类使用线程上下文加载器,从而有效建立一条与类加载器层次结构相反方向的“通道”达到正确的委托。

 假如说加载rt.jar的是启动类加载器(Bootstrap ClassLoader),它要加载一个开发人员提供的类,开发人员提供的类是由系统类加载器来加载的,这时候尴尬了,应该双亲委派模型没有双向的,只有单向的委托父加载器帮我加载,没有说双向的可以委托子加载器来帮我加载.这时候就可以用线程上下文加载器给jndi指定它的加载器是系统类加载器.

 

 

你可能感兴趣的:(JAVA基础)