类加载器双亲委托机制详解

理论了解:html

关于类加载器的双亲委托机制基本上都据说过,面试时可能偶尔也会被问到,可是可能都是网上去找了一个理论性的答案临时了解了一下,并未对它究竟是个什么样的机制有深刻的了解,因此接下来准备深刻了解它,在了解以前固然得有理论作为支撑。java

在以前【http://www.cnblogs.com/webor2006/p/8905978.html】已经对类加载器的一个层次关系有了一个大致的了解,回顾一下:web

在父亲委托机制中,各个加载器按照父子关系造成了树形结构【注意:并不是物理上的树形结构,而是逻辑上的树形结构】,附了根类加载器以外,其他的类加载器都有且只有一个父加载器。下面来看另一张图:面试

其中loader1和loader2是自定义类加载器,所谓的类加载器的双亲委托机制是这样:假如说想要经过loader1来加载本身所编写的Sample类,而类加载器双亲委托机制并非直接由loader1直接来加载Sample类,而是先转交给loader1的父亲系统类加载器来完成,而系统类加载器又会转交给扩展类加载器去完成, 而因为扩展类加载器还有父亲根类加载器,因此说又会转到根类加载器去加载,因为它木有父加载器了,此时根类加载器就开始尝试去加载Sample类了,可是!此时根类加载器是没法加载Sample类的,为何?缘由以下:ide

也就是说此时根类加载器会加载失败,可是并非失败了就立马就返回了,而是把加载的任务又返回给它的下一级子类,也就是扩展类加载器,而扩展类加载器也加载不了自定义的类,缘由跟根类加载器相似,以下:spa

也就是不进行相应路径的配置其扩展类加载器加载Sample类确定也失败了,因而继续传给它的下一级子类系统类加载器(也叫应用加载器),而它加载的规则以下:3d

也就是通常状况下系统类加载会成功的加载我们定义的Sample类了,经过这么一个从底部往上和从顶部往下的过程其实最终加载Sample类是由系统类加载器完成的,而非是load1完成,不过会将结果返回给load1,以上的整个过程则为双亲委托机制(也叫父亲委托机制),大致能够概括为:某一个类加载器想要加载一个类,它并不是立马本身去加载该类,而是委托给它的父亲去加载,若是父亲还有父亲则继续委托,直到根类加载器了没父亲了则由它去加载,若是加载不成功则会从上到下进行委托加载,整个链上只要有一个加载器能加载成功,则最终的加载结果就是成功的,最终流程就会返回到第一次想加载类的类加载器。htm

【注意】:上面的加载机制只是在标准的hospot虚拟机上是这样的,固然JDK里采用的也是标准的这种方式,可是不并代码其它的JVM都是采用的这种双亲委托机制,了解一下。对象

再来看一下该图:blog

这个顺序恰好就是我们以前所描述的。下面再针对不一样的加载类具体描述一下其加载的特性:

  • Bootstrap ClassLoader【启动类加载器】:负责加载$JAVA_HOME中jre/lib/rt.jar里全部的class,由C++实现,不是ClassLoader子类。
  • Extension ClassLoader【扩展类加载器】:负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包。
  • App ClassLoader【系统类加载器/应用类加载器】:负责加载classpath中指定的jar包及目录中的class。

另外还需了解一个概念,仅了解既可:若是有一个类加载器可以成功加载Test类,那么这个类加载器被称为定义类加载器,全部能成功返回Class对象引用的类加载器(包括定义类加载器)都被称为初始类加载器。具体理解以下:

实验:

既然已经对类加载器的双亲委托机制有了必定的了解,下面编写代码来使用一下类加载器:

在加载自定义类以前,我们先来加载系统的类,以下:

在运行以前,先来看一下getClassLoader()这个方法的说明:

编译运行:

这也是根类加载器的职责所在,再来回顾下:

好,那接下来再来加载我们本身定义的类C,以下:

而AppClassLoader的职责以下:

那我们来看一下AppClassLoader类:

位置Launcher类中,而这个类是ide根据class文件反编译出来的,由于它并非开源的,以下:

其中了解一下它的类继承关系:

相关文章
相关标签/搜索