类加载过程包括:加载->验证->准备->解析->初始化。按此顺序开始(非完成、可能交叉进行)
初始化过程就是执行类构造器<clinit>(为static变量、static{}块顺序组成)
触发初始化的情况:
1)new、getstatic、putstatic、incokestatic 4条字节码时,常见为new实例化、读取设置静态字段(除被final修饰编译常量外)、调用静态方法
2)初始化一个类时,若父类未初始化,先触发父类初始化
3)对类进行反射调用时
4)虚拟机启动时,含main的类先初始化
类加载完后,才会进行实例初始化<init>(非静态变量、非静态初始化块、构造器)
加载:
完成以下三件事:
1)通过一个类的全限定名来获取定义此类的二进制字节类
2)讲这个字节流所代表的经验存储结构转化为方法区的运行时数据机构
3)在Java堆中生成一个代表这个类的Class对象,作为方法区这些数据的访问入口
验证:
确保Class文件的字节流中包含的信息符合虚拟机要求,并且不会威海虚拟机自身安全
1)文件格式验证
2)元数据验证
3)字节码验证
4)符号引用验证
准备:
为类变量分配内存并设置类变量初始值,这些内存在方法区中进行分配
static:初始值0,null
static final :根据ConstantValue属性
解析:
讲常量池内的符号引用替换为直接引用,针对类或接口、字段、类方法、接口方法,分别对应于常量池的CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info、CONSTANT_InterfaceMethodref_info
1)类或接口解析:比如类D中解析C(符号引用N)虚拟机会吧代表N的全限定名传给D的类加载器去加载C,在加载过程中,可能会触发其他的加载动作,如C的父类和实现的接口
2)字段解析
3)类方法解析
4)接口方法解析
初始化:
执行类构造器<clinit>()方法