连接阶段包含验证,准备,解析三个阶段
第一个阶段--验证:主要目的是为了载入有害的字节流导致系统崩溃。因为java的.class文件是可以通过任何途径产生的。不检查的话会出很大的问题。
由于此阶段非常重要。所以检查也是非常严谨的。主要包含以下几个方面
1.文件格式验证:是否Class文件格式的规范
2.元数据验证:对数据类型进行校验
3.字节码验证:对方法提进行校验
程序通过上面3个验证后,也不能保证就一定不会出问题。因为不能通过程序准确的检查出程序能在一定时间内结束运行
4.符号引用验证:对非自身的各种符号引用(常量池的符号引用)进行匹配校验。这个验证发生在解析阶段中,为了保证解析能正常执行
第二阶段--准备阶段:为类变量赋初值,不给实例变量赋值,这儿的初值指的是零值
public static int value = 123;
value在准备阶段过后的初始值为0而不是123,而把value赋值的putstatic指令将在初始化阶段才会被执行
第三阶段--解析阶段:将常量池的符号引用转化为直接引用,主要针对接口或类,字段。接口方法,类方法的符号引用。分别对应于常量池中的CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info、CONSTANT_InterfaceMethodref_info四种常量类型。
1.接口或类解析
如果这是个类,非数组类。那虚拟机会把类的全限定名交给该类的类加载器。
如果是数组类。虚拟机会加载数组元素类型。虚拟机会生成此数组维度和元素的数组对象
2.字段解析
对字段进行解析时,会先在本类中查找是否包含有简单名称和字段描述符都与目标相匹配的字段,如果有,则查找结束;如果没有,则会按照继承关系从上往下递归搜索该类所实现的各个接口和它们的父接口,还没有,则按照继承关系从上往下递归搜索其父类,直至查找结束,查找流程如下图所示: