第一步:加载
1.通过类的全限定名获取这个类的二进制字节流;
2.字节流的静态存储结构转化为方法区的运行时数据结构;
3.在java堆里生成一个类对象,作为方法区的访问入口(Class对象)。
第二步:验证
1.验证Class文件的标识:魔数 Magic Number;
2.验证主副版本号;
3.验证常量池(常量类型及数据结构是否符合规定,UTF-8是否符合标准);
4.Class文件的每个部分(字段表,方法表等);
5.源数据验证(父类验证,继承验证,final验证);
6.字节码验证(指令验证);
7.符号引用验证(通过符号引用是否能找到相应的字段,方法,类)。
第三步:准备
为类变量分配内存,并且设置类变量的初始化阶段。
只对static类变量进行内存分配。
static int n=2;初始化值为0,而不是2,因为这个时候还没开始执行任何java方法(clinit)。
static final int n = 2;对应到常量池ConstantValue,在准备阶段必须被赋值为2。
第四步:解析
对符号引用进行解析。
直接引用:指向目标的指针或偏移量。
解析简单来说就是把符号引用变为直接引用。
主要涉及类,接口,方法,字段
第五步:初始化
<init>类的实例构造器
<clinit>静态变量和静态代码块的初始化