返回

字节码文件的加载过程:JVM 如何将代码加载到内存?

前端

加载一个 Java 程序,需要经历如下步骤:

  1. 类加载(Loading):在这一步,Java 虚拟机(JVM)使用类加载器将编译后的 Java 字节码文件加载到内存中。
  2. 验证(Verification):在验证步骤中,JVM 会对字节码文件进行校验,确保其符合 Java 虚拟机规范,没有安全漏洞或不兼容之处。
  3. 准备(Preparation):准备步骤为类加载的下一阶段,它为刚刚加载的类分配内存,并设置类变量的初始值。
  4. 解析(Resolution):在解析步骤中,JVM 将类文件中引用的符号(例如类、方法和字段)替换为它们的实际内存地址。
  5. 初始化(Initialization):在初始化步骤中,JVM 会执行类的静态初始化程序(static initializer),并为类的实例变量分配内存并设置初始值。

以下是每个步骤的更详细说明:

  1. 类加载(Loading) :类加载器负责从文件系统或网络加载字节码文件。Java 虚拟机为类加载器提供了一组标准的 API,以便它们可以很容易地完成这项任务。有许多不同的类加载器,每种类加载器都有自己独特的搜索路径。例如,启动类加载器负责加载 Java 虚拟机所需的类,而系统类加载器负责加载用户定义的类。

  2. 验证(Verification) :一旦类加载器加载了字节码文件,JVM 就会对其进行验证。验证过程确保字节码文件符合 Java 虚拟机规范,并且没有安全漏洞或不兼容之处。验证过程分为以下几个步骤:

    • 字节码验证(Bytecode Verification) :这一步检查字节码指令是否正确,并且不会产生安全漏洞。例如,它会确保数组不会被索引超出范围,并且不会调用不存在的方法。
    • 类型检查(Type Checking) :这一步检查类的类型是否兼容。例如,它会确保方法参数具有正确的类型,并且字段具有正确的类型。
    • 符号解析(Symbol Resolution) :这一步将类文件中引用的符号(例如类、方法和字段)解析为它们的实际内存地址。
  3. 准备(Preparation) :准备步骤为类加载的下一阶段。在准备步骤中,JVM 会为刚刚加载的类分配内存,并设置类变量的初始值。类变量是在类声明时声明的变量,并且在类的所有实例之间共享。类变量的初始值通常是 0 或 null。

  4. 解析(Resolution) :在解析步骤中,JVM 将类文件中引用的符号(例如类、方法和字段)替换为它们的实际内存地址。这一步是必要的,因为类文件中的符号在加载时可能是未知的。例如,一个类可能引用另一个类,而该类可能还没有加载。

  5. 初始化(Initialization) :在初始化步骤中,JVM 会执行类的静态初始化程序(static initializer)。静态初始化程序是在类声明时声明的代码块,并且在类的所有实例加载之前执行。静态初始化程序通常用于初始化类变量或执行其他一次性操作。

通过这五个步骤,Java 虚拟机将字节码文件加载到内存中,并准备执行。当您运行一个 Java 程序时,JVM 会根据这些步骤加载和初始化程序所需的类。