当前位置: 首页 > news >正文

JVM 类加载过程

一、加载(Loading)

目标:把字节码文件(.class)“读入 JVM”,生成类的 “半成品”(Class 对象)。

  • Bootstrap ClassLoader(启动类加载器)
    • 负责加载 JVM 核心类库(如 java.lang 包),用 C++ 实现(不同 JVM 有差异),无对应的 Java 类。
  • Platform ClassLoader(平台类加载器)
    • 加载 Java 标准库扩展(如 java.sqljavax 包),JDK 9 后从 Extension ClassLoader 改名而来。
  • App ClassLoader(应用类加载器):  
    • 加载项目自己写的类、第三方库(classpath 路径下的类),是开发中最常用的加载器。

类加载器(不同 JDK 版本的差异)

  • 低版本 JDK
    • 启动类加载器:负责加载rt.jar(包含 Java 核心类库)中的类。
    • 扩展类加载器:负责加载ext目录下的扩展类库中的类。
    • 系统类加载器(System ClassLoader):负责加载classpath中程序员自己编写的类。
  • 高版本 JDK(9+,引入模块化思想)
    • 启动类加载器:仍负责加载 JDK 核心类库。
    • 平台类加载器:替代低版本的扩展类加载器,负责加载 Java 平台扩展的非核心类。
    • 应用类加载器:替代低版本的系统类加载器,负责加载classpath中的类。
    • 变化:rt.jarext目录消失,类库被拆分为多个模块(.jmod文件),不同模块由不同类加载器加载。

流程:类加载器按 双亲委派机制 工作(优先让父加载器尝试加载,保证核心类不被篡改),最终找到字节码文件,读入内存并生成 Class 对象,存入方法区。

二、链接(Linking)

目标:把 “半成品类” 变成可执行的 “成品”,拆成 验证、准备、解析 三步:

1. 验证(Verify)
  • 检查字节码是否符合 JVM 规范(比如魔数是否是 0xCAFEBABE、语法是否合法),防止恶意 / 错误字节码搞崩 JVM。
2. 准备(Prepare)
  • 给类的静态变量分配内存 + 设置默认值(比如 static int num = 10,准备阶段会先设 num = 0,真正赋值在初始化阶段)。
  • 注意:静态常量(static final)直接赋 “用户写的值”(比如 static final int num = 10,准备阶段就会设 num = 10 )。
3. 解析(Resolve)
  • 把符号引用替换成直接引用:比如代码里写 Object obj = new Object(),编译后是 “符号引用”(类似 “找名为 Object 的类”),解析阶段会换成内存地址(直接引用),让 JVM 真正能找到对应的类。

三、初始化(Initialization)

目标:执行类的静态代码块、给静态变量赋 “用户写的值”(比如 static int num = 10 在这里真正赋值为 10 )。

  • 触发时机:首次用类的静态成员、创建对象、反射调用等(遵循 主动使用规则 )。
  • 流程:按代码顺序执行静态变量赋值、静态代码块,完成后类才算真正 “可用”。

关键总结

  1. 类加载器:用 “双亲委派” 保证类加载安全,避免核心类被篡改。
  2. 链接阶段:验证字节码合法性 → 给静态变量分配内存 → 把符号引用转成内存地址。
  3. 初始化:执行静态逻辑,给静态变量赋最终值,让类真正 “激活”。

类加载器获取

(1)方式 1:通过当前类的 getClassLoader() 获取

ClassLoader appClassLoader = ReflectTest.class.getClassLoader();

  • 逻辑
    • ReflectTest.class 拿到当前类的 Class 对象,调用 getClassLoader(),获取 “加载当前类的类加载器”。
    • 因 ReflectTest是项目 classpath 内的自定义类,加载它的就是 应用类加载器
  • 作用:验证 “自定义类由应用类加载器加载”。

(2)方式 2:通过 ClassLoader.getSystemClassLoader() 获取

ClassLoader appClassLoader2 = ClassLoader.getSystemClassLoader();

  • 逻辑
    • ClassLoader 是类加载器基,静态方法 getSystemClassLoader() 直接返回 应用类加载器
    • 这是 Java 提供的 “直接获取应用类加载器” 的标准写法。
  • 作用:更直接获取应用类加载器,与方式 1 对比,结果一致。

(3)方式 3:通过线程上下文类加载器获取

ClassLoader appClassLoader3 = Thread.currentThread().getContextClassLoader();
System.out.println("应用类加载器:" + appClassLoader3);

  • 逻辑
    • 每个 Java 线程默认有 “上下文类加载器(Context ClassLoader)”,默认就是 应用类加载器
    • 通过 Thread.currentThread() 拿到当前线程,调用 getContextClassLoader() 获取。
  • 作用:框架(如 Tomcat )中常用,可动态修改上下文类加载器,实现复杂加载逻辑(此处演示默认情况 )。
http://www.xdnf.cn/news/1107919.html

相关文章:

  • Django母婴商城项目实践(四)
  • OpenEuler操作系统中检测插入的USB设备并自动挂载
  • perftest测试连接是否稳定shell脚本
  • Typecho博客系统与WebSocket实时通信整合指南
  • Ubuntu快速搭建QT开发环境指南,5000字解析!!
  • 前端note
  • 【Lucene/Elasticsearch】**Query Rewrite** 机制
  • RabbitMQ面试精讲 Day 1:RabbitMQ核心概念与架构设计
  • PostgreSQL HOT (Heap Only Tuple) 更新机制详解
  • [es自动化更新] Updatecli编排配置.yaml | dockerfilePath值文件.yml
  • AI之DL之VisualizationTool:ai-by-hand-excel的简介、安装和使用方法、案例应用之详细攻略
  • Redis过期策略与内存淘汰机制面试笔记
  • [es自动化更新] 策略体系 | 策略源(容器镜像)
  • Java中的方法传参机制
  • 【B题成品论文】2025APMCM亚太杯中文赛B题成品论文(无偿分享)
  • Java 大视界:基于 Java 的大数据可视化在智慧城市能源消耗动态监测与优化决策中的应用(2025 实战全景)
  • 舒尔特方格训练小游戏流量主微信小程序开源
  • 数据分析库 Pandas
  • SQL新手入门详细教程和应用实例
  • 【MediaSoup】MS_DUMP打印转换为PLOGI的形式
  • 13. https 是绝对安全的吗
  • 二叉树算法进阶
  • Redis渗透思路总结
  • 第七章应用题
  • JVM--虚拟线程
  • Spring Boot 中使用 Lombok 进行依赖注入的示例
  • RMSNorm实现
  • linux----------------------线程同步与互斥(上)
  • linux_线程概念
  • 基于开源AI智能名片链动2+1模式S2B2C商城小程序的营销直播质量提升策略研究