一个类从加载到使用,一般会经历下面的这个过程:
加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载
1.加载
编译:
X.java->X.class->JVM
class汇总的类的加载
双亲委派模型:子类加载器会请示父类加载器检查层层上询, 上面没加载的, 再层层下派;
- 启动类加载器: Bootstrap ClassLoader
- 扩展类加载器: Extension ClassLoader
- 应用程序类加载器: Application ClassLoader
- 自定义类加载器: XXX
自定义加载器->Application->Extension->Bootstrap
2.验证
校验你加载进来的.class文件内容,是否符合Java虚拟机规范
- 格式验证: 0xCAFEBABE开头/是否有编码以外的字符等
- 元数据验证: 比如是否继承了final类(不允许的)/父类为接口或抽象类的子类,是否实现了抽象方法等;
- 字节码验证: 方法调用时任何指令不会跳到方法体以外的的字节码指令上;
- 符号引用验证: 符号引用类中的类/字段/方法的可访问性(是否能被当前类访问)
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.卸载
略
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。