文章目录
1、概述
2、过程1:Loading(加载)阶段
(1)加载的理解
- 所谓加载,简而言之就是将Java类的字节码文件加载到机器内存中,并在内存中构建出Java类的原型——类模型
- 类的加载器只涉类加载的第一阶段——类的记载阶段,后面的链接初始化与类加载器无关。
(2)类模型与Class的位置
- 类模型的位置
加载的类在JVM中创建相应的类结构,类结构会存储在方法区(JDK1.8之前:永久代;JDK1.8及之后:元空间)。 - Class实例的位置
类将.class文件加载至元空间后,会在堆中创建一个Java.lang.Class对象,用来封装类位于方法区内的数据结构,该Class对象是在加载类的过程中创建的,每个类都对应有一个class类型的对象。
3、过程2:Liking(链接)阶段
(1)验证
- 这个家段主要是验证字节码文件是否合法
(2)准备
- 准备阶段主要是为类的静态变量分配内存,并将其初始化为默认值。(默认初始化)
- static final修饰的量是常量了,我们在前端编译成字节码文件时,就已经在常量池生成了该常量,那么在准备阶段直接就会进行显示初始化。
(3)解析
- 解析阶段主要将类、接口、字段、和方法的符号引用转换为直接引用。
4、过程3:Initialization(初始化)阶段
- 初始化阶段,简而言之,为类的静态变赋予正确的初始值。
- 初始化阶段的重要工作是执行类的<clinit<>()方法,这个方法是由类静态成员的赋值语句以及static代码块中的语句合并产生。所以初始化阶段会执行静态变量的显示赋值和执行static代码块。
- 以下是static+final修饰的常量赋值的几种情况;
/**
*
* 类加载的三阶段:加载-->链接-->初始化
* 链接:验证-->准备-->解析
* 说明:使用static + final修饰的字段的显式赋值的操作,到底是在那个阶段进行赋值的?
* 情况1:在链接阶段的准备阶段进行赋值
* 情况2:在初始化阶段进行赋值
*
* 结论:1、只有static修饰的变量一定是在初始化阶段进行显示赋值的
* 2、static+final修饰的常量,如果在赋值时使用了方法或者构造器,则在初始化阶段进行显示赋值;
* 3、static+final修饰的常量,如果在赋值时没有使用方法或者构造器,则在链接阶段的准备阶段进行显式赋值
*/
public class Code {
public static int a=11;//初始化阶段进行显示赋值
public static final int INT_CONSTANT=10;//在链接的准备阶段进行赋值
public static Integer INTEGER_CONSTANT=Integer.valueOf(100);//初始化阶段进行显示赋值
public static final Integer INTEGER_CONSTANT2=Integer.valueOf(100);//初始化阶段进行显示赋值
public static final String s0="yiheng";//在链接的准备阶段进行显示赋值;
public static final String s1=new String("yiheng666");//初始化阶段进行显示赋值;
public static String s2="yiheng000";//s2的显示赋值在初始化阶段
public static final int NUM1=new Random().nextInt(10);//NUM1在初始化阶段进行显示赋值
}
- <clinit<>()方法线程安全性问题
- 类的初始化情况:主动使用vs被动使用
主动使用:
被动使用
- 通过子类调用父类的静态变量·
5、过程4:类的Using(使用)
不过多描述
6、过程5:类的Unloading(卸载)
条件很苛刻