寻找类字节码文件并构造出类在JVM内部表示的组件.负责运行时查找和装入Class字节码文件java
查找装载class字节码文件数组
执行校验,准备和解析步骤,其中解析步骤时可选的缓存
检查装载Class文件的正确性安全
给类的静态变量分配存储空间网络
将符号引用转换为直接引用app
对类的静态变量,方法,代码块执行初始化操做jvm
最顶层的装载器,它不是ClassLoader的子类,采用C++编写,所以在JAVA中不可见。主要负责装载JRE核心类库。能够经过jvm启动参数-Xbootclasspath改变该加载器加载的路径函数
主要负责加载JRE扩展目录ext下的包,能够经过-D java.ext.dirs选项指定目录源码分析
负责加载当前工程目录下,classpath下的包或者class文件post
其中Extention ClassLoader & AppClassLoader是ClassLoader的子类,根加载器是扩展加载器的父加载器,扩展加载器是应用加载器的父加载器。在默认状况下使用应用加载器
类加载采用“全盘负责委托机制”。
“全盘负责”:在类加载时指定一个ClassLoader,除非显示声明其余的加载器,不然该类所依赖的类以及引用的类都由该加载器加载。
“委托机制”:类加载时优先委托父加载器寻找并加载目标类,只有在父加载器没有找到的状况下,才从本身的classpath路径下查找并加载目标类。该点主要是出于安全的考虑,在classpath路径下定义JDK中已经存在的类,因为该机制,JDK中的类都由父加载器开始查找并加载.每一个加载器都有缓存,在委托时优先查找缓存,若是缓存中存在,那么直接返回,否者才执行查找和加载
类文件被加载后,在JVM内部对应拥有一个java.lang.Class类描述对象,类的每一个实例拥有类描述对象的引用,类描述对象拥有类加载器的引用
Bootstrap ClassLoader-->Extention ClassLoader-->AppClass Loader即Bootstrap ClassLoader最早启动,接着是Extenion ClassLoader,最后是AppClass Loader
1.定义Bootstrap ClassLoader加载路径(sun.boot.class.path)
2.建立Extention ClassCloader
3.建立App ClassLoader并设置App ClassLoader的父类:Extention ClassCloader
该类中定义了Bootstrap ClassLoader加载路径,同时建立了Extention ClassLoader以及AppClassLoader,以下是Bootstrap ClassLoader加载路径信息
从输出路径上看Bootstrap ClassLoader主要加载的是jre/lib目录下的资源.即JVM Runtime核心库
1.根据查找路径得到路径(jav.ext.dirs)下文件
2.将文件路径转换为URL
3.调用父类构造函数,建立ExtClassLoader并设置父加载器
以下是java.ext.dirs的输出信息
1.得到java.classs.path路径下的全部文件
2.解析文件路径为URL
3.调用父类构造函数建立AppClassLoader并设置父类
Java.class.path输出信息
/work/new_workspace/aaa/bin
java.lang.Object
java.lang.ClassLoader
java.security.SecureClassLoader
java.net.URLClassLoader
ExtClassLoader
AppClassLoader
能够经过getParent()得到当前加载器的父加载器
为何得到ExtClassLoader的父加载器为null?这和每一个加载器都有一个父加载器违背.这个属于正常现象.具体缘由以下:
1.从ExtClassLoader构造函数super(getExtURLs(dirs), null, factory);能够看出此时传入的就是null
2.Bootstrap ClassLoader是由C/C++编写的,它自己是虚拟机的一部分,不是一个JAVA类,没法在java代码中获取它的引用,凡是sun.boot.class.path路径下的包以及类都是由它加载。JVM初始化sun.misc.Launcher建立Extension ClassLoader和AppClassLoader实例。并将ExtClassLoader设置为AppClassLoader的父加载器。BootstrapClassCloader没有父加载器,可是它却能够做为一个ClassLoader的父加载器。好比ExtClassLoader。这也能够解释以前经过ExtClassLoader的getParent方法获取为Null的现象.咱们能够分析getParent()的源码
父加载器能够直接由外界指定,若是外界不指定,那么采用AppClassLoader做为父加载器
//在建立ExtClassLoader时,采用super(getExtURLs(dirs), null, factory).因此得到的是null
查找给定名称的资源。资源的名称是一个/分隔的路径名称标识资源,优先查找父加载器,若是找不到在从Bootstrap ClassLoader路径中查找并加载
查找给定名称的全部资源。资源的名称是一个/分隔的路径名称标识资源,优先查找父加载器,若是找不到在从Bootstrap ClassLoader路径中查找并加载,该模式下支持正则匹配
采用AppClassLoader加载给定名称的资源
采用AppClassLoader加载给定名称的全部资源
查找具备给定名称的资源。类加载器实现应覆盖此方法以指定在哪里查找资源
查找具备给定名称的全部资源。类加载器实现应覆盖此方法以指定在哪里查找资源
loadClass(String name) & loadClass(String name, boolean resolve)name指定了类装载器的名字,必须使用全限定名。resolve告诉装载器是否须要解析该类。在初始化以前,应该考虑进行类解析工做。并非全部的类都须要解析的。若是JVM只须要知道该类是否存在或者找出该类的超类,那么就不须要解析该类
将类文件字节码数组装换成JVM内部的java.lang.Class对象,字节数组能够从本地系统,远程网络获取
从本地文件系统载入Class文件,若是本地文件系统中不存在该Class文件,抛出ClassNotFoundError。该方法是JVM默认使用的装载器
该方法查看ClassLoader是否已经加载了某个类,若是载入就返回Class对象,不然返回null,若是强行载入已经载入的类会抛出异常
1.编写一个类继承ClassLoader
2.重写findClass 方法
3.在findClass中调用defineClass便可
contextClassLoader只是一个成员变量,经过setContextClassLoader()方法设置,经过getContextClassLoader()得到。
每一个Thread都有一个相关联的ClassLoader,默认是AppClassLoader。而且子线程默认使用父线程的ClassLoader除非子线程特别设置
常见的用法是将Class文件按照某种加密手段进行加密,而后按照规则编写自定义的ClassLoader进行解密,这样咱们就能够在程序中加载特定了类,而且这个类只能被咱们自定义的加载器进行加载,提升了程序的安全性。