当前位置: 首页 > 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.dtcms.com/a/275580.html

相关文章:

  • 5. JVM 的方法区
  • 云端docker小知识
  • Vue Vue-route (6)
  • 【SpringAI】7. 基于 milvus 的向量检索
  • Go语言生态成熟度分析:为何Go还无法像Java那样实现注解式框架?
  • 个人面经250712
  • JDK的Stream API使用详解
  • HTML(上)
  • 基于Opencv的缺陷检测实战
  • 《目标检测模块实践手册:从原理到落地的尝试与分享》第一期
  • 服务器怎么跑Python项目?
  • 【408考研知识点全面讲解计算机学科专业基础综合(408)】——数据结构之排序
  • 无法打开windows安全中心解决方案
  • 从基础加热到智能生态跨越:艾芬达用创新重构行业价值边界!
  • 14. 请谈一下浏览器的强缓存和协商缓存
  • Django母婴商城项目实践(四)
  • 算法魅力-BFS解决最短路问题
  • 鸿蒙开发竖的线
  • Typecho集成PHPMailer实现邮件订阅功能完整指南
  • 如何查看服务器当前用户的权限
  • Windows X64环境下mysql5.6.51安装指南
  • 联邦学习客户端异构数据特征对齐:挑战、方法与应用
  • 如何防范金融系统中的SQL注入攻击
  • QWidget的属性
  • Java设计模式实战:备忘录模式与状态机模式的“状态管理”双雄
  • 基于MCP的CI/CD流水线:自动化部署到云平台的实践
  • 英语单词学习系统
  • 周末总结(2024/07/12)
  • 13. https 是绝对安全的吗
  • 代码审计-Struts2漏洞分析