加载
加载主要是将程序类(可以从zip、jar、war、网络、动态代理生成....等等)加载到jvm中,主要完成如下三件事:
a、通过一个类的全限定名来获取此类的二进制字节流
b、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
c、在java对中生成一个代表这个类的Class对象,作为方法区这些数据的访问入口
验证
验证时为了确保class文件的字节流中包含的信息符合jvm的要求,不会对jvm产生危害。大致可以划分为如下
四个阶段
**1、文件格式验证**(验证字节流是否符合Class文件格式的规范)验证点如下:
a、是否以魔数0xCAFEBABE开头
b、常量池中的常量是否有不被支持的常量类型......
**2、元数据验证**(对字节码描述的信息进行语义分析)验证点如下:
a、这个类是不是父类
b、这个类是否继承了不允许被继承的类
**3、字节码验证**(进行数据流和控制流分析,保证被校验的类的方法在运行时不会危害jvm)
a、类的方法体进行分析
b、保证方法体中的类型转换有效
**4、符号引用验证**:(验证符号引用转化为直接引用)
a、符号引用中的类、字段、方法的访问性是否可被当前类访问
b、确保解析动作能正常执行如果无法通过符号引用验证,会
抛出一个java.lang.IncompatibleClassChangeError异常的子类,
如:java.lang.IllegalAccessError、java.lang.NoSuchFieldError、
java.lang.NoSuchMethodError
准备
准备阶段正式为类变量分配内存并设置类变量初始值的阶段(这里的初始值是数据类型的零值,比如定义的类变
量public static int value = 123,那么在准备阶段过后初始值为0而不是123,而赋值为123是在程序被编译后也
就是在初始化阶段才会赋真正的值),这些内存都将在方法区中进行分配(仅包含类变量-被static修饰的变量,而
不包括实例变量)
解析
解析阶段是jvm将常量池内的符号引用替换为直接引用的过程。
符号引用:是一组符号来秒速所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义的定位到目标
直接引用:直接引用是可以直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄,直接引用是和
虚拟机实现的内存布局相关,同一个符号引用在不同的虚拟机实例上对应的直接引用一般也一样
解析的动作主要针对:类和接口、字段、类方法、接口方法
初始化
类加载的最后一步,真正执行类中定义的java程序代码或者是字节码,在准备阶段给变量赋初始值,在初始阶段
则是真正赋变量对应的值。
【参考文献】深入理解Java虚拟机:JVM高级特性与最佳实践