JVM-类加载(4)
类加载的三个阶段
加载
将类的字节码加载到方法区中,内部采用 C++ 的 instanceKlass 描述java类
其重要的field有:
- _super 父类
- _fields 成员变量
- _methods 方法
- _constants 常量池
- _vtable 虚方法表
- _itable 接口方法表
- _class_loader 类加载器
- _java_mirror java的类镜像
链接
链接阶段又分为三个小阶段:
验证
验证是否符合JVM规范,安全性检查
准备
为static变量分配空间,设置默认值
- static变量在JDK7之前存储与 instanceKlass 末尾,从JDK7开始,存储于_java_mirror末尾
- static变量分配空间和赋值是两个步骤,分配空间在准备阶段,赋值在初始化阶段完成
- 如果static变量是final的基本类型,那么编译阶段值就确定了,赋值在准备阶段完成
- 如果static变量是final的,但属于引用类型,那么赋值也会在初始化阶段完成
解析
将常量池的符号引用解析为直接引用
初始化
初始化实际上是调用<cinit>()v,虚拟机会保证这个类的构造方法的线程安全。
什么时候会发生初始化
- main方法所在的类,总是会优先初始化
- 首次访问这个类的静态变量或静态方法时
- 子类初始化会联动父类的初始化
- 子类访问父类的静态变量,只会触发父类初始化
- 执行Class.forName时
- new对象时
什么时候不会发生初始化
- 访问类的静态常量时
- 类对象.class时
- 创建该类的数组时
- 执行类加载器的loadClass方法时
- Class.forName的第二个参数(是否初始化)为false时