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

JVM 的类加载机制

JVM 的类加载机制是 Java 虚拟机动态加载、链接和初始化类的核心机制,它遵循严格的流程和规则,确保类的安全性和一致性。以下是详细说明:


类加载的流程

类加载分为 加载(Loading)→ 链接(Linking)→ 初始化(Initialization) 三个阶段:

  1. 加载(Loading)
    • 任务:查找并加载类的二进制字节流(如 .class 文件)。
    • 结果:在内存中生成一个代表该类的 Class 对象(方法区中)。
    • 数据来源:可以是本地文件、网络、JAR 包等。
  2. 链接(Linking)
    • 验证(Verification):检查字节码是否符合 JVM 规范(如魔数、语法合法性)。
    • 准备(Preparation):为类的静态变量分配内存并设置默认初始值(如 int 初始化为 0)。
    • 解析(Resolution):将常量池中的符号引用(如类名、方法名)转换为直接引用(内存地址)。
  3. 初始化(Initialization)
    • 执行类的 <clinit> 方法(编译器自动生成,包含静态变量赋值和静态代码块)。
    • 触发条件:首次主动使用类时(如 new 对象、访问静态变量/方法、反射调用等)。

双亲委派模型(Parent Delegation Model)

类加载器通过层级关系协作,确保核心类库的安全性,避免重复加载。

  1. 层级结构
    • Bootstrap ClassLoader(启动类加载器):
      加载 JAVA_HOME/lib 下的核心类库(如 rt.jar),由 C++ 实现,无父类。
    • Extension ClassLoader(扩展类加载器):
      加载 JAVA_HOME/lib/ext 目录的扩展类。
    • Application ClassLoader(应用类加载器):
      加载用户类路径(classpath)下的类,默认的类加载器。
    • 自定义 ClassLoader:用户可继承 ClassLoader 实现自定义加载逻辑。
  2. 工作流程

示例:加载用户自定义的 java.lang.String 类时,最终会由 Bootstrap ClassLoader 加载核心库的 String,避免用户篡改。

- 收到加载请求时,优先委派给父类加载器处理。  
- 若父类无法完成(在自己的搜索范围内找不到类),子类才会尝试加载。
  1. 优势
    • 避免重复加载,确保类全局唯一。
    • 保护核心类库不被自定义类覆盖。

打破双亲委派的场景

某些场景需要绕过双亲委派机制:

  1. SPI 服务加载(如 JDBC)
    Java 核心库(如 java.sql.Driver)由 Bootstrap ClassLoader 加载,而 SPI 实现类(如 MySQL 驱动)由应用类加载器加载。此时通过 线程上下文类加载器(Thread Context ClassLoader) 实现父类加载器请求子类加载器完成加载。
  2. 热部署/热加载
    如 Tomcat 为每个 Web 应用提供独立的类加载器,支持应用级类隔离和重新加载。
  3. 自定义类加载器
    用户可重写 loadClass() 方法改变委派逻辑。

类初始化的条件

类必须初始化的情况(主动引用):

  • new 实例对象、读写静态字段(非 final)、调用静态方法。
  • 反射调用(如 Class.forName("类名"))。
  • 初始化子类时,若父类未初始化,会触发父类初始化。

被动引用示例

class Parent {static int value = 10; static { System.out.println("Parent init!"); }
}
class Child extends Parent {static { System.out.println("Child init!"); }
}
// 访问 Parent.value 不会初始化 Child 类

类的卸载

  • 条件:类的 Class 对象无引用,且对应的类加载器被回收。
  • 实现:由 JVM 的垃圾回收机制完成,通常发生在方法区(元空间)内存不足时。

总结

JVM 类加载机制通过 双亲委派模型分阶段加载 确保类的安全加载与隔离,同时支持灵活扩展(如 SPI、热部署)。理解其原理有助于解决类冲突、实现动态加载等高级场景。


文章转载自:
http://amphigenous.ciuzn.cn
http://administratrix.ciuzn.cn
http://attune.ciuzn.cn
http://bushman.ciuzn.cn
http://amblygonite.ciuzn.cn
http://boniface.ciuzn.cn
http://childbearing.ciuzn.cn
http://acolyte.ciuzn.cn
http://bespangle.ciuzn.cn
http://allocatee.ciuzn.cn
http://achondroplasia.ciuzn.cn
http://bedspread.ciuzn.cn
http://carrolline.ciuzn.cn
http://blacklead.ciuzn.cn
http://bilirubin.ciuzn.cn
http://borne.ciuzn.cn
http://avoid.ciuzn.cn
http://chorography.ciuzn.cn
http://amerika.ciuzn.cn
http://amphitrichous.ciuzn.cn
http://apartness.ciuzn.cn
http://balladmonger.ciuzn.cn
http://admitted.ciuzn.cn
http://awesome.ciuzn.cn
http://canonise.ciuzn.cn
http://annihilationism.ciuzn.cn
http://bespoke.ciuzn.cn
http://aqua.ciuzn.cn
http://caza.ciuzn.cn
http://biogasification.ciuzn.cn
http://www.dtcms.com/a/212876.html

相关文章:

  • 贪心算法应用:贝尔曼-福特松弛问题详解
  • 贪心算法应用:Ford-Fulkerson最大流问题详解
  • 自训练NL-SQL模型
  • webpack优化方法
  • Linux系统之----磁盘硬件
  • 【C++进阶篇】红黑树的封装(赋源码)
  • 线程池实战——数据库连接池
  • Python中字典(dict)知识详解应用
  • Vue.extend
  • CentOS7更新 GLIBC 2.25
  • 区块链可投会议CCF C--APSEC 2025 截止7.13 附录用率
  • ISO 26262-5 区分失效模式
  • 阿里千问系列:Qwen3技术报告解读(下)
  • 英语科研词汇现象及语言演变探讨
  • 用 Python 构建自动驾驶的实时通信系统:让车辆“交流”起来!
  • YOLOV8涨点技巧之空间通道协作注意力(SCCA)-应用于自动驾驶领域
  • 类欧几里得算法(floor_sum)
  • git 把一个分支A的某一个 commit 应用到另一个分支B上
  • LLM 使用本地模型 提取新生成 文本 的token ID序列
  • 使用中文作为map的可以,需要注意什么
  • 差分数组知识笔记
  • java 加密算法的简单使用
  • 医学写作人才管理策略
  • Leetcode 刷题记录 11 —— 二叉树第二弹
  • 获取 Stream 对象的方式
  • 内存管理(第五、六章)
  • RocketMQ 深度解析:消息中间件核心原理与实践指南
  • AUTOSAR图解==>AUTOSAR_SRS_ICUDriver
  • 关于 Web 安全:5. 认证绕过与权限控制分析
  • 前端面经-虚幻引擎5