返回

将无形变有形,JVM 中类加载的过程详解

后端

导语

在 Java 程序中,类是程序的基本组成单位,程序通过创建对象来使用类,但是类本身是如何在 JVM 中被加载的呢?类加载是一个复杂的过程,涉及多个阶段和不同的类加载器。在本文中,我们将深入浅出地讲解类加载的各个阶段,探讨类加载器是如何将无形的代码转化为有形存在的对象,以及它们在 Java 程序中的作用。

类加载的七个阶段

一个类的生命周期从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)和卸载(Unloading)。

1. 加载(Loading)

加载阶段是类加载的第一个阶段,在这个阶段,类加载器会从文件系统或网络中读取类的二进制数据,并将其存储在内存中。类加载器使用不同的机制来加载类,例如系统类加载器会加载 Java 核心库中的类,而应用程序类加载器会加载用户自定义的类。

2. 验证(Verification)

验证阶段是类加载的第二个阶段,在这个阶段,JVM 会对类进行一系列的验证检查,以确保类符合 Java 虚拟机规范。验证检查包括:

  • 字节码校验:JVM 会检查类的字节码是否符合 Java 虚拟机规范,以确保类不会执行任何非法操作。
  • 元数据校验:JVM 会检查类的元数据是否符合 Java 虚拟机规范,以确保类具有正确的格式和结构。
  • 符号引用校验:JVM 会检查类的符号引用是否指向有效的类、方法或字段,以确保类可以正确地引用其他类和成员。

3. 准备(Preparation)

准备阶段是类加载的第三个阶段,在这个阶段,JVM 会为类分配内存空间,并初始化类的静态变量。静态变量是指用 static 修饰的变量,这些变量在类加载时被初始化,并且在类的整个生命周期中都存在。

4. 解析(Resolution)

解析阶段是类加载的第四个阶段,在这个阶段,JVM 会将类的符号引用解析为直接引用。符号引用是指类、方法或字段的名称,而直接引用是指类、方法或字段的内存地址。解析过程包括:

  • 类解析:JVM 会将类的符号引用解析为类的直接引用。
  • 方法解析:JVM 会将方法的符号引用解析为方法的直接引用。
  • 字段解析:JVM 会将字段的符号引用解析为字段的直接引用。

5. 初始化(Initialization)

初始化阶段是类加载的第五个阶段,在这个阶段,JVM 会执行类的静态代码块和构造方法。静态代码块是指用 static 关键字修饰的代码块,这些代码块在类加载时执行,并且在类的整个生命周期中只执行一次。构造方法是类的特殊方法,用于创建类的实例,当创建类的实例时,JVM 会执行类的构造方法。

6. 使用(Using)

使用阶段是类加载的第六个阶段,在这个阶段,JVM 会将类加载到内存中,并可以使用类来创建对象。当创建一个类的实例时,JVM 会分配内存空间给对象,并调用类的构造方法来初始化对象。

7. 卸载(Unloading)

卸载阶段是类加载的最后一个阶段,在这个阶段,JVM 会将类从内存中卸载。类卸载的条件包括:

  • 类不再被任何对象引用。
  • 类所属的类加载器被卸载。
  • JVM 内存不足。

类加载器的作用

类加载器在 Java 程序中扮演着重要的角色,它们负责将类加载到 JVM 内存中。类加载器有以下作用:

  • 隔离不同的类:类加载器可以将不同的类加载到不同的类加载器中,从而隔离不同的类,防止它们相互影响。
  • 提高安全性:类加载器可以提高 Java 程序的安全性,因为它们可以控制哪些类可以被加载到 JVM 内存中。
  • 提高性能:类加载器可以提高 Java 程序的性能,因为它们可以缓存已经加载过的类,从而避免重复加载。

总结

类加载是 Java 虚拟机的重要组成部分,它负责将类加载到内存中,并使其可以使用。类加载是一个复杂的过程,涉及多个阶段和不同的类加载器。了解类加载的过程和类加载器的作用,有助于我们更深入地理解 Java 虚拟机的工作原理。