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

JVM类加载过程

  JVM类加载过程是将类的字节码文件(.class)加载到内存,并转换为运行时数据结构的过程,核心分为加载(Loading)、链接(Linking)、初始化(Initialization)三个阶段,其中链接又包含验证、准备、解析三个子阶段。以下是详细流程:


1. 加载(Loading)

  • 任务:查找并加载类的二进制数据。
  • 过程
    • 通过类的全限定名(如 com.example.MyClass)获取字节码。
    • 将字节码解析为方法区(元空间)的运行时数据结构。
    • 在堆中创建该类的 java.lang.Class 对象,作为访问方法区数据的入口。
  • 类加载器
    • Bootstrap ClassLoader:加载JRE核心库(rt.jar等),C++实现。
    • Extension ClassLoader:加载扩展库(jre/lib/ext目录)。
    • Application ClassLoader:加载用户类路径(ClassPath)下的类。
    • 自定义ClassLoader:用户可继承 ClassLoader 实现自定义加载逻辑。

2. 链接(Linking)

(1) 验证(Verification)
  • 确保字节码合法且符合JVM规范:
    • 文件格式验证:检查魔数(0xCAFEBABE)、版本号等。
    • 元数据验证:检查继承、方法重写等语义(如是否实现抽象方法)。
    • 字节码验证:分析代码逻辑(如操作数栈类型匹配)。
    • 符号引用验证:检查引用的类/方法/字段是否存在(发生在解析阶段)。
(2) 准备(Preparation)
  • 类变量(静态变量) 分配内存并设置默认初始值(非显式赋值):
    static int value = 123;  // 准备阶段 value = 0,而非123
    
    • 常量(static final)在此阶段直接赋值:
    static final int CONST = 123;  // 准备阶段 CONST = 123
    
(3) 解析(Resolution)
  • 将常量池中的符号引用替换为直接引用
    • 符号引用:用字符串描述引用的目标(如 java/lang/Object)。
    • 直接引用:指向目标在内存中的指针、偏移量等。

3. 初始化(Initialization)

  • 执行类构造器 <clinit>()
    • 为类变量赋显式初始值(如 static int value = 123;)。
    • 执行静态代码块(static {})。
  • 触发条件(首次主动使用类时):
    • 创建实例(new)、访问静态变量/方法。
    • 反射调用(Class.forName())、初始化子类等。
  • 线程安全:JVM保证 <clinit>() 的同步执行。

4. 使用(Using)

  • 类完成初始化后,可正常创建对象、调用方法、访问字段。

5. 卸载(Unloading)

  • 条件:类的 Class 对象无引用,且无存活实例。
  • 由GC回收方法区(元空间)数据。

关键特性

  1. 双亲委派模型

    • 类加载请求先委派给父加载器处理。
    • 避免重复加载,保证核心类安全(如用户无法自定义 java.lang.String)。
  2. 惰性加载

    • 类在首次“主动使用”时才初始化(如 new、访问静态字段等)。
  3. 类加载示例

    public class Main {public static void main(String[] args) {System.out.println(Child.value); // 父类初始化,子类不初始化}
    }
    class Parent {static int value = 10;static { System.out.println("Parent init!"); }
    }
    class Child extends Parent {static { System.out.println("Child init!"); }
    }
    // 输出:Parent init!  10
    

常见问题

  • ClassNotFoundException:类加载器找不到类定义。
  • NoClassDefFoundError:编译时存在类,运行时缺失。
  • 打破双亲委派:如JDBC通过 Thread.currentThread().setContextClassLoader() 实现SPI加载。

理解类加载过程对解决类冲突、热部署、模块化开发等场景至关重要。

http://www.dtcms.com/a/265557.html

相关文章:

  • 车载电子电气架构 --- 从车窗演进看车联网的需求、发展与选择
  • 2025年游戏鼠标推荐,游戏鼠标推荐,打CSGO(罗技、雷蛇、卓威、ROG、漫步者、赛睿、达尔优)
  • 前端-HTML-day2
  • 从生活实例看:点积、内积和矩阵乘法如何玩转机器学习
  • 物联网MQTT协议与实践:从零到精通的硬核指南
  • I/O 进程 7.2
  • Mysql锁机制与优化实践以及MVCC底层原理剖析
  • TensorFlow 安装使用教程
  • 6. 常见K线形态(楔形与旗形)
  • Laravel8中调取腾讯云文字识别OCR
  • 中文语境下的视频生成革命:百度 MuseSteamer 的“产品级落地”启示录
  • 手机内存融合是什么意思
  • Redis 的特性、工作机制与性能优化全解(含搭建实战教程)
  • 用 vLLM 在两张 RTX 3090 上部署 Qwen2.5-14B BF16全量大模型的完整过程
  • 替换springboot打好jar包中的class文件
  • Python 异步爬虫(aiohttp)高效抓取新闻数据
  • 前端开发中的 Base64 图片革命:从链接到嵌入的性能优化
  • Go爬虫实时性能监控方案
  • 利用人名语言分类案例演示RNN、LSTM和GRU的区别(基于PyTorch)
  • 【学习线路】机器学习线路概述与内容关键点说明
  • git 中删除提交历史
  • 闲庭信步使用SV搭建图像测试平台:第二十七课——图像的腐蚀
  • Windows DOS CMD 100
  • PostgreSQL-XL之 序列(Sequence)
  • 深度学习2(逻辑回归+损失函数+梯度下降)
  • 基于Spring Boot + MyBatis-Plus + Thymeleaf的评论管理系统深度解析
  • Spring Boot + Screw 一键生成数据库设计文档
  • GitHub 解码指南:用 AI 赋能,五步快速掌握任意开源项目
  • WordPress 站点漏洞利用:数据库恶意注入与多重感染的案例分析
  • 大数据环境搭建指南:基于 Docker 构建 Hadoop、Hive、HBase 等服务