JVM 类加载的过程&类加载器&双亲委派机制

Java 类加载过程分为:加载 → 验证 → 准备 → 解析 → 初始化,其中前四步称为"连接(Linking)"。

文章目录

一、每一步JVM都在做什么?

1. 加载(Loading)------ 把字节码"搬进 JVM"

JVM 做的事:

  • 根据类的全限定名

  • 找到 .class 文件

  • 读入方法区(元空间)

  • 创建 Class 对象

来源可能是:

  • 本地 class 文件

  • jar 包

  • 网络

  • 动态生成(代理类)

⚠️ 这一步 还没执行任何 Java 代码


2. 验证(Verification)------ JVM 的"安检门"

目的:保证字节码是合法、安全的

主要验证内容:

  • 文件格式验证

  • 元数据验证

  • 字节码验证

  • 符号引用验证

如果失败:

java 复制代码
java.lang.VerifyError

3. 准备(Preparation)------ 给"类变量"分配空间

关键点(高频考):

  • 只给 static 变量 分配内存

  • 默认值

java 复制代码
static int a = 10;

准备阶段结果:

java 复制代码
a = 0

4.解析(Resolution)------ 把"符号引用"变成"直接引用"

  • 常量池里的符号引用

  • 转成内存地址

比如:

  • 方法

  • 字段

⚠️ 有些 JVM 会 延迟到真正使用时才解析


5. 初始化(Initialization)------ 真正执行 Java 代码

这是 唯一会执行 Java 代码的阶段

做的事:

  • 执行 <clinit> 方法

    • static 变量显式赋值

    • static 代码块

示例:

java 复制代码
static int a = 10;
static {
    a = 20;
}

初始化后:

java 复制代码
a = 20

二、类什么时候会被初始化?

会触发初始化的场景:

  1. new 对象

  2. 访问静态变量(非 final)

  3. 调用静态方法

  4. 反射

  5. 初始化子类,父类先初始化

  6. JVM 启动时的主类


不会触发初始化的场景(陷阱)

java 复制代码
public static final int A = 10;
  • 编译期常量

  • 不会触发类初始化


三、 父子类加载顺序(常考)

java 复制代码
class Parent {
    static {
        System.out.println("Parent");
    }
}

class Child extends Parent {
    static {
        System.out.println("Child");
    }
}
java 复制代码
new Child();

输出:

复制代码
Parent
Child

规则:

先父后子,静态优先


四、类加载器和双亲委派机制

虽然不是"过程的一步",但几乎必追。

类加载器层级:

  • Bootstrap

  • Extension

  • Application

  • 自定义

双亲委派作用:

  • 防止核心类被篡改

  • 保证类唯一性

相关推荐
Mr_Xuhhh3 小时前
深入理解JVM:从原理到实践的完整指南
jvm
Rick19933 小时前
Java内存参数解析
java·开发语言·jvm
明湖起风了4 小时前
mqtt消费堆积
java·jvm·windows
Free Tester4 小时前
如何判断 LeakCanary 报告的严重程度
java·jvm·算法
wgzrmlrm7411 小时前
如何解决ORA-28040没有匹配的验证协议_sqlnet.ora版本兼容设置
jvm·数据库·python
wgzrmlrm7413 小时前
如何从SQL中提取年份或月份:EXTRACT与日期函数用法
jvm·数据库·python
ruan11451416 小时前
关于HashMap--个人学习记录
java·jvm·servlet
__土块__1 天前
大厂后端一面模拟:从线程安全到分布式缓存的连环追问
jvm·redis·mysql·spring·java面试·concurrenthashmap·大厂后端
fly spider2 天前
一文概括 JVM 核心内容
jvm
brahmsjiang2 天前
Java类加载机制解析:从JVM启动到双亲委派,再到Android的特殊实现
android·java·jvm