聊聊 Java 的类加载机制一

一说到这个主题,想到的应该是双亲委派模型,不过讲的包括但不限于这个,主要内容是参考深入理解 Java 虚拟机书中的介绍,
一个类型的生命周期包含了七个阶段,加载,验证,准备,解析,初始化,使用,卸载。

  • 加载

  1. 通过一个类的全限定名来获取定义此类的二进制字节流
  2. 将这个字节流代表的静态存储结构转化为方法区的运行时数据结构
  3. 在内存中生成了一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口
  • 验证

  1. 文件格式验证
  2. 元数据验证
  3. 字节码验证
  4. 符号引用验证
  • 准备

准备阶段是正式为类中定义的变量(即静态变量,被static修饰的变量)分配内存并设置类变量初始值的阶段

  • 解析

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

以上验证准备解析 三个阶段又合称为链接阶段,链接阶段要做的是将加载到JVM中的二进制字节流的类数据信息合并到JVM的运行时状态中。

  • 初始化

类的初始化阶段是类加载过程的最后一个步骤,也是除了自定义类加载器之外将主动权交给了应用程序,其实就是执行类构造器()方法的过程,()并不是我们在 Java 代码中直接编写的方法,它是 Javac编译器的自动生成物,()方法是由编译器自动收集类中的所有类变量的复制动作和静态句块(static{}块)中的语句合并产生的,编译器收集的顺序是由语句在原文件中出现的顺序决定的,静态语句块中只能访问定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以复制,但是不能访问,同时还要保证父类的执行先于子类,然后保证多线程下的并发问题

最终,方法区会存储当前类类信息,包括类的静态变量、类初始化代码(定义静态变量时的赋值语句 和 静态初始化代码块)、实例变量定义、实例初始化代码(定义实例变量时的赋值语句实例代码块和构造方法)和实例方法,还有父类的类信息引用。