【二】ClassLoader及双亲委托机制

1、Java语言系统自带有三个类加载器:

- Bootstrap ClassLoader 最顶层的加载类,主要加载核心类库,%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等。另外需要注意的是可以通过启动jvm时指定-Xbootclasspath和路径来改变Bootstrap ClassLoader的加载目录。比如java -Xbootclasspath/a:path被指定的文件追加到默认的bootstrap路径中。我们可以打开我的电脑,在上面的目录下查看,看看这些jar包是不是存在于这个目录。(加载基础类。eg:int、String、float)

- Extention ClassLoader 扩展的类加载器,加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件。还可以加载-D java.ext.dirs选项指定的目录。

- Appclass Loader也称为SystemAppClass 加载当前应用的classpath(eclipse中的workspace)的所有类。

2、加载类的顺序

1. Bootstrap CLassloder-----根类加载器

2. Extention ClassLoader-----扩展类加载器

3. AppClassLoader-----系统类加载器

3、每个类加载器都有一个父加载器(除了Bootstrap加载器)。父加载器不是父类

URLClassLoader的源码中并没有找到getParent()方法。这个方法在ClassLoader.java中。

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

AppClassLoader的父加载器是ExtClassLoader,而ExtClassLoader的父加载器是null(但是此时会交由Bootstrap类加载器去加载,int的加载器是null,但是是由Bootstrap类加载器加载)。

4.双亲委派机制

一个类加载器查找class和resource时,是通过“委托模式”进行的。

用序列描述一下:

1. 一个AppClassLoader查找资源时,先看看缓存是否有,缓存有从缓存中获取,否则委托给父加载器。

2. 递归,重复第1部的操作。

3. 如果ExtClassLoader也没有加载过,则由Bootstrap ClassLoader出面,它首先查找缓存,如果没有找到的话,就去找自己的规定的路径下,也就是sun.mic.boot.class下面的路径。找到就返回给子类加载器,没有找到,让子加载器自己去找。

4. Bootstrap ClassLoader如果没有查找成功,则ExtClassLoader自己在java.ext.dirs路径中去查找,查找成功就返回给子类加载器,查找不成功,再向下让子加载器找。

5. ExtClassLoader查找不成功,AppClassLoader就自己查找,在java.class.path路径下查找。找到就返回给子类加载器。如果没有找到就让子类找,如果没有子类会怎么样?抛出各种异常。

ClassLoader类中的loadClass方法定义了上述的双亲委托,在自定义ClassLoader时(自定义ClassLoader可以加载任意位置的.class文件并对.class文件中的内容进行解密后加载到jvm中),一般不用重写loadClass方法(此时自定义的ClassLoader类的父加载器是AppClassLoader),需要重写findClass()方法并且在findClass()中调用defineClass()方法(它能将class二进制内容转换成Class对象,如果不符合要求的会抛出各种异常。

双亲委派模型的优点:

Java类伴随其类加载器具备了带有优先级的层次关系,确保了在各种加载环境的加载顺序。  

保证了运行的安全性,防止不可信类扮演可信任的类。

eg:自定义一个java.lang.Object类型,此时的话也不会与bootstrap类加载器路径下的java.lang.Object类型冲突,因为会首先加载bootstrap类加载器路径下的java.lang.Object类型,如果没有双亲委托模型的话那么就出现先加载自定义类的情况,此时的话就会出现问题。

猜你喜欢

转载自blog.csdn.net/Jack_PJ/article/details/87979698
今日推荐