类的加载流程包含:加载、验证、准备、解析、初始化java
做为第一个阶段,虚拟机须要完成了之后三个步骤缓存
确保被加载类的正确性,包含检测如下信息安全
为类的静态变量分配内存,并将其初始化默认值bash
将类中的符号引用转换为直接引用网络
解析阶段就是虚拟机将常量池内符号引用替换为直接引用,解析的动做主要是针对类的接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。数据结构
为类的静态变量赋予正确的初始值,到了初始阶段,才开始真正执行类中定义的Java程序代码。jvm
示例图布局
==注意:这里父类加载器并非经过继承关系来实现的,而是采用组合实现的==加密
在java虚拟机的角度来讲只存在两种不一样的类加载器spa
在开发者的角度来讲,类的加载器能够大体划分为三类
类加载的方式
双亲委派机制的流程:若是一个类加载器收到了一个类加载的请求,首先他不会尝试本身加载该类,而是把这个请求委托给父类加载器加载该类,依次向上传递,所以,全部的类记载请求都会请求到启动类加载器中,父类加载器在他的搜索范围内没有找到所须要的类时,即没法完成该类的加载,子加载器才会尝试本身去加载该类,若是尚未找到,那么直接抛出异常
示例流程详解
双亲委派机制的意义
代码示例
// 首先判断该类型是否已经被加载
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
//若是没有被加载,就委托给父类加载或者委派给启动类加载器加载
if (parent != null) {
//若是存在父类加载器,就委派给父类加载器加载
c = parent.loadClass(name, false);
} else {
//若是不存在父类加载器,就检查是不是由启动类加载器加载的类,经过调用本地方法native Class findBootstrapClass(String name)
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
复制代码
一般状况下,咱们都是直接使用系统类加载器。可是,有的时候,咱们也须要自定义类加载器。好比应用是经过网络来传输 Java类的字节码,为保证安全性,这些字节码通过了加密处理,这时系统类加载器就没法对其进行加载,这样则须要自定义类加载器来实现。自定义类加载器通常都是继承自 ClassLoader类,从上面对 loadClass方法来分析来看,咱们只须要重写 findClass 方法便可。
自定义类加载器的核心在于对字节码文件的获取,若是是加密的字节码则须要在该类中对文件进行解密