图片
加载
加载阶段是类加载的第一步,它的主要任务是找到并加载类的字节码文件。
在加载阶段,JVM会查找并加载类的字节码文件,这个过程通常从类路径(Classpath)中查找类文件,然后将它们读入内存。
如下图所示:
图片
JVM通过类加载器(ClassLoader)从类路径(Classpath)中查找类文件。
加载后的类字节码被存储在方法区(在JVM规范中被称为Metaspace)中,并为每个类创建一个Class对象。
验证
一旦类被加载到内存中,JVM会对字节码文件进行验证,以确保其完整性和合法性。
如下图所示:
图片
这包括检查字节码文件的结构,以防止恶意代码或错误的字节码文件,确保加载的类符合JVM规范,不会危害JVM的安全。
验证主要分为3个步骤:
1.文件格式验证
在这个阶段,JVM首先检查字节码文件的格式是否合法。
这包括检查文件头是否以魔数开头(通常为0xCAFEBABE),以及文件版本号是否合适。
2.语义验证 在这个阶段
JVM会对字节码进行语义分析,确保代码中不会存在语法错误和语义错误。
3.字节码验证 在这个阶段
字节码验证是最复杂的一步,它检查字节码是否符合Java语言规范。
这包括验证操作码是否合法,跳转指令是否正确,以及栈操作是否匹配。
如果字节码验证失败,JVM会认为这个类是不安全的,并拒绝加载它。
准备
Java虚拟机的类准备阶段是类加载过程的重要步骤之一,它负责为类的静态变量分配内存并初始化这些变量。
如下图所示:
图片
准备阶段为类的静态变量分配内存,并初始化这些变量为默认值(通常为零值,例如0或null)。
例如,对于以下代码:
public class MyClass {
public static int x = 10;
}
在准备阶段,x 的值将被初始化为 10。
解析
解析阶段的主要任务:是将类或接口中的符号引用转化为直接引用。
如下图所示:
图片
解析过程包括以下步骤:
a. 根据符号引用的类名找到对应的类。
b. 验证类的可访问性和继承关系,确保访问不会违反访问控制规则。
c. 找到符号引用对应的字段或方法,获取其内存地址或偏移量。
d. 最终将符号引用替换为直接引用,以便在运行时直接访问类、字段或方法。
初始化
初始化阶段是类加载的最后一步,它负责执行类的初始化代码。
在初始化阶段,静态代码块会被执行,静态变量会被赋予初始值。
如下图所示:
图片
在初始化阶段中,JVM会执行以下操作:
1.为类的静态变量分配内存,并设置初始值
在加载阶段中,JVM会为类的静态变量分配内存,并设置默认初始值。
2.执行类的静态代码块
在初始化阶段中,JVM会执行类的静态代码块,这些静态代码块中可以包含任意的Java代码。
总之:JVM的类加载过程包括加载、验证、准备、解析和初始化五个阶段,确保类在被使用之前被正确加载和初始化。