一个类从加载到使用,一般会经历下面的这个过程:
加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载

1.加载

编译:

X.java->X.class->JVM

class汇总的类的加载

双亲委派模型:子类加载器会请示父类加载器检查层层上询, 上面没加载的, 再层层下派;
  1. 启动类加载器: Bootstrap ClassLoader
  2. 扩展类加载器: Extension ClassLoader
  3. 应用程序类加载器: Application ClassLoader
  4. 自定义类加载器: XXX

自定义加载器->Application->Extension->Bootstrap

2.验证

校验你加载进来的.class文件内容,是否符合Java虚拟机规范
    1. 格式验证: 0xCAFEBABE开头/是否有编码以外的字符等
    1. 元数据验证: 比如是否继承了final类(不允许的)/父类为接口或抽象类的子类,是否实现了抽象方法等;
    1. 字节码验证: 方法调用时任何指令不会跳到方法体以外的的字节码指令上;
    1. 符号引用验证: 符号引用类中的类/字段/方法的可访问性(是否能被当前类访问)

3.准备

static变量:分配内存空间,设置默认的初始值

byte/short/int/long->0/0L
float/double=0.0f/0.0d
boolean=false
reference=null

4.解析

符号引用替换为直接引用的过程

直接引用: 目标的指针/相对偏移量/间接定位到目标的句柄
符号引用: class文件中的字面符号引用;

就是将classs文件中的类/接口/字段/方法解析为实际的目标指针/相对偏移量/目标句柄等的过程;

原因就是: classs文件是编译来的; 编译的时候并无法得知执行时类/接口/字段/方法的内存位置.

5.初始化

初始化变量为实际赋值的数据;

static int a = getValue()
在准备阶段只会给a分配空间和给初始值0, 在初始化阶段才会调用getValue()来赋值初始化a;

6.使用

7.卸载


丰木
322 声望19 粉丝

遇见超乎想象的自己!