Java 编译后的字节码 Class 文件加载到虚拟机后才能运行和使用。
一、类加载过程
包括三个步骤, Loading 加载,Linking 链接,Initializing初始化;第二步又可以细分为 Verification 验证,Preparation 准备,Resolution 解析3小步。
1、Loading加载
将二进制字节码加载到内存。
2、Linking 链接
分3小步,1)Verification 验证,校验 class 文件是否符合 jvm 规范;2)Preparation,将 class 文件静态成员变量赋默认值;3)Resolution,将 class 文件常量池中的类、方法、属性等符号引用转换为直接内存地址的直接引用。
3、Initializing初始化
调用类初始化代码 clinit 时,给静态成员变量赋初始值。
二、类加载器
ClassLoader 类加载器,是一个抽象类,class文件都是由它的具体子类加载的,分为3个层次,顶级加载器 BootstrapClassLoader,然后是ExtClassLoader,AppClassLoader,以及自定义实现的类加载器。
BootstrapClassLoader,加载/jre/lib/下的核心类库,包括rt.jar,resources.jar,jce.jar等等,加载范围为sun.boot.class.path。
ExtClassLoader,加载 /jre/lib/ext 下的扩展包,加载范围为 java.ext.dirs。
AppClassLoader,加载 classpath 指定的内容,包括平时我们自己写的各种 Class,加载范围为 java.class.path。
三、双亲委派机制
有了上面的类加载器的层次,开始引入双亲委派机制。
一个 class 文件,如果有自定义ClassLoader,则先去里面找,内部维护一个缓存,如果缓存里有就不加载了,如果缓存里没有就先去上一级的AppClassLoader里找,有则返回,没有继续向上一级的ExtClassLoader里找,有则返回,没有则向BootstrapClassLoader里找,如果没有则返回向下一级里找,有则返回没有继续向下一级查找;一直到自定义类加载器,有则返回没有就会报 ClassNotFound 异常,这种机制就叫双亲委派机制。
四、自定义类加载器
继承 ClassLoader,重写 findClass 方法即可;如果想打破双亲委派机制,需要重写loadClass 方法。
五、懒加载 Lazyloading
按需加载,需要用的时候再去加载 class。