用来动态加载class文件到内存当中java
BootStrapClassLoader:称为启动类加载器,是Java类加载层次中最顶层的类加载器,
负责加载JDK中的核心类库,如:rt.jar、resources.jar、charsets.jar、sunrsasign.jar、jsse.jar、jce.jar等(加载jdk/jre/lib/下的部分jar包以及jdk/jre/classes下的class文件)
ExtensionClassLoader:称为扩展类加载器,负责加载Java的扩展类库,默认加载jdk/jre/lib/ext/目下的全部jar
AppClassLoader:称为系统类加载器,负责加载应用程序classpath目录下的全部jar和class文件算法
用户还能够根据须要定义自已的ClassLoader,自定义的ClassLoader都必须继承自java.lang.ClassLoader类(包括Java提供Extension ClassLoader和App ClassLoader)api
Bootstrap ClassLoader不继承ClassLoader,由于它不是一个普通的Java类,底层由C++编写,已嵌入到了JVM内核当中。当JVM启动后,Bootstrap ClassLoader也随着启动,负责加载完核心类库后,并构造Extension ClassLoader和App ClassLoader类加载器安全
ClassLoader使用的是双亲委托模型来搜索类的
每一个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系)。
Bootstrap ClassLoader自己没有父类加载器,但能够用做其它ClassLoader实例的父类加载器。
当一个ClassLoader实例须要加载某个类时,它会先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,
首先由最顶层的类加载器Bootstrap ClassLoader试图加载,
若是没加载到,则把任务转交给Extension ClassLoader加载,
若是也没加载到,则转交给App ClassLoader 进行加载,
若是它也没有加载获得的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。
若是它们都没有加载到这个类时,则抛出ClassNotFoundException异常。
不然将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。网络
为何要使用双亲委托这种模型?由于这样能够避免重复加载,
当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。
考虑到安全因素,咱们试想一下,若是不使用这种委托模式,那咱们就能够随时使用自定义的String来动态替代java核心api中定义的String类型,这样会存在很是大的安全隐患,
而双亲委托的方式,就能够避免这种状况,由于String已经在启动时就被类加载器(Bootstrcp ClassLoader)加载,因此用户自定义的ClassLoader永远也没法加载一个本身写的String,
除非你改变JDK中ClassLoader搜索类的默认算法。spa
JVM在搜索类的时候,如何断定两个class是相同?
JVM在断定两个class是否相同时,不只要判断两个类名是否相同,并且要判断是否由同一个类加载器加载的。
只有二者同时知足的状况下,JVM才认为这两个class是相同的。
就算两个class是同一份class字节码,若是被两个不一样的ClassLoader实例所加载,JVM也会认为它们是两个不一样class。对象
1.继承java.lang.ClassLoader
2.重写父类的findClass方法继承
由于JDK已经在loadClass方法中帮咱们实现了ClassLoader搜索类的算法,
当在loadClass方法中搜索不到类时,loadClass方法就会调用findClass方法来搜索类,因此咱们只需重写该方法便可。
如没有特殊的要求,通常不建议重写loadClass搜索类的算法。内存