Java 中的类加载机制分为加载、连接(验证、准备、解析)、初始化三个阶段
加载:
根据类的权限来获取定义此类的二进制字节流
将这个字节流代表的静态存储结构转化为方法区中的动态存储结构
在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区中这个类的访问入口
连接:
验证:为了验证 class 文件中的字节流符合 Java 虚拟机的规范,包括文件的格式;元数据验证等
准备:为类变量分配内存并设置类变量的初始值,分配的内存在方法区中
解析:将常量池中的符号引用转化为直接引用的过程;符号引用与虚拟机实现的内存布局无关,只是使用一组符号来描述所引用的目标。class 文件中的常量池包括字面量与符号引用(字段的名称和描述符、方法的名称和描述符、类和接口的权限定名),在 class 文件中不会保存各个方法字段的最终布局信息,因此这些符号引用不经过转化是无法得到真正的内存入口地址;直接引用和虚拟机实现的内存布局有关,可以是直接指向目标的指针,偏移量或者指向目标的句柄。包括类和接口的解析、字段的解析、类方法的解析、接口方法的解析。此过程主要是静态链接,方法主要为静态方法和私有方法。对于动态链接是在运行时通过动态分派来实现的
初始化阶段:
- 该阶段才会真正执行类种定义 Java 代码。初始化是执行类构造器 clinit() 方法的过程,该方法由编译器自动收集类中所有类变量的赋值动作和静态语句块的语句合并而成。且保证子类的 clinit() 方法执行之前会执行父类的 clinit() 方法,接口除外,接口的实现类执行 clinit() 方法时不会执行接口的 clinit() 方法。clinit() 方法可以不存在,比如没有静态语句块和静态类变量