类加载过程:验证,连接与初始化
loading 加载
此阶段JVM的作用是将字节码从不同的数据源(.class文件,jar包以及网络传输)转化为二进制字节流传输加载到内存中,并且生成一个代表该类的 java.lang.Class 对象
Verification 验证
此阶段是保证JVM安全性的重要部分,只有符合JVM标准的通过了二进制字节流校验的才会进入下一阶段
在此阶段中,JVM会检查:
确保二进制字节流的格式符合预期 (魔数:cafebabe)
是否所有的方法都遵循了访问控制关键字的限定
确保变量进行正确初始化
检查变量是否被赋予相应的类型的值
方法调用的参数类型与个数是否匹配
Preparation 准备阶段
JVM进行对类变量(静态变量)的分配内存并且进行初始化
例如:
public static String test1 = "测试";
public String test2 = "测试2";
public static final String test3= "测试3";
以上代码块中,test1会被分配内存初始化,但是不会被初始化为"测试",而是null,test2不会被分配内存,test3由于是一个常量,则会被直接赋值为"测试3",而并非null
Resolution 解析
此阶段将常量池中的符号引用转化为直接引用
符号引用:
以一组符号进行对引用目标进行描述
在编译过程时,Java类不知道引用类的实际地址,因此只能使用符号进行代替
例如 com.package.dao.TestDaoImpl 引用了 com.package.dao.Test 类,在对于TestDaoImpl 的编译时并不知道 Test类的实际地址,因此只能使用符号com.package.dao.Test
直接进行引用通过对符号进行解析,找到引用的实际内存地址
Initialization 初始化
最后一步,进行初始化,此阶段作为类加载的最后步骤,在准备阶段,类变量已经被赋值过默认的初值(0,null)在这一阶段,类变量将会被赋予代码所期待的值,执行了类构造器方法的过程
String test = new String("测试");
如上代码块是使用new进行实例化一个字符串对象,在此阶段将会对test进行实例化
如果类中有语句:private static int a = 10,它的执行过程是这样的,首先字节码文件被加载到内存后,先进行链接的验证这一步骤,验证通过后准备阶段,给a分配内存,因为变量a是static的,所以此时a等于int类型的默认初始值0,即a=0,然后到解析,到初始化这一步骤时,才把a的真正的值10赋给a,此时a=10。