对ClassLoader的一些简单总结

Posted learn-ding

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对ClassLoader的一些简单总结相关的知识,希望对你有一定的参考价值。

参考:http://blog.csdn.net/briblue/article/details/54973413,http://blog.csdn.net/qbg19881206/article/details/8890600,http://zyjustin9.iteye.com/blog/2022654,https://www.cnblogs.com/tuning/p/6943427.html

一、ClassLoader的作用?

  ClassLoader翻译过来就是类加载器。jvm启动的时候,并不会一次性加载所有的class文件,而是根据需要去动态地加载。ClassLoader的作用就是将class文件加载到jvm虚拟机中去。

二、java自带的三个类加载器

  1。Bootstrap ClassLoader。最顶层的加载类,主要加载核心类库,加载%JRE_HOME%\\lib下的rt.jar、resources.jar、charsets.jar和class等。

  2。Extention ClassLoader。扩展的类加载器,负责加载目录%JRE_HOME%\\lib\\ext目录下的jar包和class文件。

  3。Appclass Loader,也称为SystemAppClass,加载当前应用的classpath的所有类。

  4。我们可以自己写类加载器,加载类和资源。

三、类加载器间的关系

  AppClassLoader的父加载器是ExtClassLoader,ExtClassLoader的父加载器是Bootstrap ClassLoader。

  如果一个ClassLoader创建时如果没有指定parent,那么它的parent默认就是AppClassLoader。

四、类加载器的加载顺序

  类加载器之间采用双亲委托的方式进行加载class。

  一个类加载器查找class和resource时,是通过“委托模式”进行的。它首先判断这个class是不是已经加载,如果没有的话就交给父加载器进行查找是否已加载,父加载器如果也没有加载过,就交给更上层的类加载器查找,直至找到已加载这个class的类加载器,返回这个类,或者直到Bootstrap ClassLoader,如果Bootstrap classloader已加载,则直接返回,如果没加载就进行查找。如果没有找到,就交给下级加载器去查找加载,如果下级加载器没有加载到,就交给下级去加载,加载到即返回,直至最下层的加载器。

五、线程的contextClassLoader

  1)contextClassLoader只是Thread类一个成员变量,通过setContextClassLoader()方法设置,通过getContextClassLoader()获取。

  每个Thread都有一个相关联的ClassLoader,默认是AppClassLoader。并且子线程默认使用父线程的ClassLoader,除非子线程特别设置。

  2)this.getClass.getClassLoader()和Thread.currentThread().getContextClassLoader()的区别

  方法一得到的Classloader是静态的,表明类的载入者是谁;方法二得到的Classloader是动态的,谁执行(某个线程),就是那个执行者的Classloader,所以子线程默认使用父线程的ClassLoader。对于单例模式的类,静态类等,载入一次后,这个实例会被很多程序(线程)调用,对于这些类,载入的Classloader和执行线程的Classloader通常都不同。

六、获得ClassLoader的3种方法

  this.getClass().getClassLoader(); // 使用当前类的ClassLoader。
  Thread.currentThread().getContextClassLoader(); // 使用当前线程的ClassLoader。
  ClassLoader.getSystemClassLoader(); // 使用系统ClassLoader,JVM下system ClassLoader通常为App ClassLoader。

七、class.getName()等方法

  当你使用class.forName(),class.getName(),class.getResource()这几个不带ClassLoader参数的方法时,默认使用当前类的ClassLoader。

八、类加载器的getResource()方法

  1.this.getClass().getResource("");//得到当前类class文件的URI目录。

  2.this.getClass().getResource("/");//得到当前的classpath的绝对URI路径。

  3.this.getClass().getClassLoader().getResource("");//得到当前ClassPath的绝对URI路径。

  4.ClassLoader.getSystemResource("");//得到的当前ClassPath的绝对URI路径。

  5.Thread.currentThread().getContextClassLoader().getResource("");得到当前ClassPath的绝对URI路径。

  Class.getResourse()和Class.getClassLoader().getResource()
  这两个getResource()是使用当前ClassLoader加载资源(即资源在classpath中),这样资源和class直接打在jar包中,避免文件路径问题。两者不同是Class的getResource()方法是从当前class文件路径查找资源,ClassLoader则是从jar包根目录查找。

九、用Classloader载入资源

  所有资源都通过ClassLoader载入到JVM里,那么在载入资源时当然可以使用ClassLoader。只是对于不同的资源还可以使用一些别的方式载入,例如对于类可以直接new,对于文件可以直接做IO等。

  1)实例化类B的三种方案

  1. 使用Class静态方法 Class.forName

  Class cls = Class.forName("com.rain.B");

  B b = (B)cls.newInstance();

  2. 使用ClassLoader

  ClassLoader cl;//可以用前面提到的几种方法

  Class cls = cl.loadClass("com.rain.B"); // 使用第一步得到的ClassLoader来载入B

  B b = (B)cls.newInstance(); // 有B的类得到一个B的实例

  3. 直接new

  B b = new B();

  2)文件载入(例如配置文件等)假设在com.rain.A类里想读取文件夹 /com/rain/config 里的文件sys.properties,读取文件可以通过绝对路径或相对路径,绝对路径很简单,在Windows下以盘号开始,在Unix下以"/"开始。对于相对路径,其相对值是相对于ClassLoader的,因为ClassLoader是一棵树,所以这个相对路径和ClassLoader树上的任何一个ClassLoader相对比较后可以找到文件,那么文件就可以找到。

  1. 直接IO

  File f = new File("C:/test/com/rain/config/sys.properties"); // 使用绝对路径

  //File f = new File("com/rain/config/sys.properties"); // 使用相对路径

  InputStream is = new FileInputStream(f);

  2. 使用ClassLoader

   因为有3种方法得到ClassLoader,对应有如下3种方法读取文件。 使用的路径是相对于这个ClassLoader的那个点的相对路径,此处只能使用相对路径

  InputStream is = null;

  is = this.getClass().getClassLoader().getResourceAsStream("com/rain/config/sys.properties"); //方法1

  //is = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/rain/config/sys.properties"); //方法2

  //is = ClassLoader.getSystemResourceAsStream("com/rain/config/sys.properties"); //方法3




以上是关于对ClassLoader的一些简单总结的主要内容,如果未能解决你的问题,请参考以下文章

CodeIgniter2的Doctrine2 CLI

Java加密解密class文件,使用classLoader动态解密class文件

java动态代理简述

ClassLoader载入指定的类需注意六个细节或报ClassNotFundEception异常总结

ClassLoader in Java

ClassLoader使用经验