类加载的过程

加载

在加载阶段,虚拟机要完成一下3件事情:

  1. 通过一个类的全限定名来获取定义此类的二进制字节流

  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构

  3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口

验证

验证是连接阶段的第一步,目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

准备

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法去中进行分配(首先,这时候进行内存分配的仅包括类变量,而不包括实例变量,实例变量将会在对象实例化时随对象一起被分配在Java堆中。其次,这里说的初始值“通常情况”是数据类型的零值)。

基本数据类型的零值如下:

数据类型 零值
int 0
long 0L
short (short)0
char '\u000'
byte (byte)0
boolean false
float 0.0f
double 0.0d
reference null

如果类字段的字段属性表中存在ConstantValue属性,那么在准备阶段变狼就会被初始化为ConstantValue属性所指定的值。

解析

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。

符号引用和直接引用之间的关联:

解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号意义进行,分别对应常量池CONSTANT_Class_info、CONSANT_Fieldref_info、CONSTANT_Methodref_info、CONSTANT_InterfaceMethodref_info、CONSTANT_MethodType_info、CONSTANT_MethodHandle_info和CONSTANT_InvokeDynamic_info7种类型常量。

  1. 类或接口的解析
  2. 字段解析
  3. 类方法解析
  4. 接口方法解析

初始化

类初始化阶段是类加载过程的最后一步,到了初始化阶段才开始执行类中定义的Java'程序代码。

<clinit>()方法执行过程中一些可能会影响程序运行行为的特点和细节: