ClassLoader原理

http://blog.csdn.net/xyang81/article/details/7292380html

 

http://blog.csdn.net/tonytfjing/article/details/47212291java

 

https://www.cnblogs.com/zhouyuqin/p/5217609.html算法

 

 

4. 类加载器的阶层体系 

讨论了这么多之后,接下来咱们仔细研究一下 Java 的类加载器的工做原理: 

当执行 java ***.class 的时候, java.exe 会帮助咱们找到 JRE ,接着找到位于 JRE 内部的 jvm.dll ,这才是真正的 Java 虚拟机器 , 最后加载动态库,激活 Java 虚拟机器。虚拟机器激活之后,会先作一些初始化的动做,好比说读取系统参数等。一旦初始化动做完成以后,就会产生第一个类加载器―― Bootstrap Loader , Bootstrap Loader 是由 C++ 所撰写而成,这个 Bootstrap Loader 所作的初始工做中,除了一些基本的初始化动做以外,最重要的就是加载 Launcher.java 之中的 ExtClassLoader ,并设定其 Parent 为 null ,表明其父加载器为 BootstrapLoader 。而后 Bootstrap Loader 再要求加载 Launcher.java 之中的 AppClassLoader ,并设定其 Parent 为以前产生的 ExtClassLoader 实体。这两个加载器都是以静态类的形式存在的。这里要请你们注意的是, Launcher$ExtClassLoader.class 与 Launcher$AppClassLoader.class 都是由 Bootstrap Loader 所加载,因此 Parent 和由哪一个类加载器加载没有关系。 api

这三个加载器就构成咱们的 Java 类加载体系。他们分别从如下的路径寻找程序所须要的类: 安全

 BootstrapLoader : sun.boot.class.path 

ExtClassLoader:      java.ext.dirs 

AppClassLoader:      java.class.path网络

加载

在加载阶段,虚拟机须要完成如下3件事情:数据结构

  • 经过一个类的全限定名来获取定义此类的二进制字节流。
  • 将这个字节流所表明的静态存储结构转化为方法区的运行时数据结构。
  • 在内存中生成一个表明这个类的java.lang.Class对象,做为方法区这个类的各类数据的访问接口。

 

 

一、原理介绍jvm

    ClassLoader使用的是双亲委托模型来搜索类的,每一个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类加载器(Bootstrap ClassLoader)自己没有父类加载器,但能够用做其它ClassLoader实例的的父类加载器。当一个ClassLoader实例须要加载某个类时,它会试图亲自搜索某个类以前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,若是没加载到,则把任务转交给Extension ClassLoader试图加载,若是也没加载到,则转交给App ClassLoader 进行加载,若是它也没有加载获得的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。若是它们都没有加载到这个类时,则抛出ClassNotFoundException异常。不然将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象.net

二、为何要使用双亲委托这种模型呢?htm

   由于这样能够避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。考虑到安全因素,咱们试想一下,若是不使用这种委托模式,那咱们就能够随时使用自定义的String来动态替代java核心api中定义的类型,这样会存在很是大的安全隐患,而双亲委托的方式,就能够避免这种状况,由于String已经在启动时就被引导类加载器(Bootstrcp ClassLoader)加载,因此用户自定义的ClassLoader永远也没法加载一个本身写的String,除非你改变JDK中ClassLoader搜索类的默认算法。

三、JVM在搜索类的时候,如何判断两个class相同呢?

   JVM在断定两个class是否相同时,不只要判断两个类名是否相同,并且要判断是否由同一个类加载器实例加载的。只有二者同时知足的状况下,JVM才认为这两个class是相同的。就算两个class是同一份class字节码,若是被两个不一样的ClassLoader实例所加载,JVM也会认为它们是两个不一样class。

    好比网络上的一个Java类org.classloader.simple.NetClassLoaderSimple,javac编译以后生成字节码文件NetClassLoaderSimple.class,ClassLoaderA和ClassLoaderB这两个类加载器并读取了NetClassLoaderSimple.class文件,并分别定义出了java.lang.Class实例来表示这个类,对于JVM来讲,它们是两个不一样的实例对象,但它们确实是同一份字节码文件,若是试图将这个Class实例生成具体的对象进行转换时,就会抛运行时异常java.lang.ClassCaseException,提示这是两个不一样的类型。

相关文章
相关标签/搜索