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

JVM基础---java类加载机制(类的生命周期,类加载器,双亲委派模型)

文章目录

  • 类的生命周期
    • 类的加载:查找并加载类的二进制数据
    • 验证
    • 准备
    • 解析
    • 初始化
  • 类加载器
    • 启动类加载器(Bootstrap ClassLoader)
    • 扩展类加载器(Extension ClassLoader)
    • 应用程序类加载器(Application ClassLoader)
    • 自定义类加载器(User-Defined ClassLoader)
  • 双亲委派模型
    • 工作原理
    • 优点
    • 打破双亲委派
    • 打破双亲委派


类的生命周期

类加载的过程包括了加载验证准备解析初始化五个阶段。在这五个阶段中,

加载验证准备初始化这四个阶段发生的顺序是确定的,解析阶段则不一定,它在某些情况下可以在初始化阶段之后开始,这是为了支持Java语言的运行时绑定(也成为动态绑定或晚期绑定)。另外注意这里的几个阶段是按顺序开始,而不是按顺序进行或完成,因为这些阶段通常都是互相交叉地混合进行的,通常在一个阶段执行的过程中调用或激活另一个阶段。

img

类的加载:查找并加载类的二进制数据

  • 任务:将类的字节码文件(.class 文件)加载到内存中。

img

  • 具体步骤

    1. 通过类的全限定名(包名 + 类名)查找字节码文件。
    2. 将字节码文件读取到内存中。
    3. 在内存中生成一个代表该类的 java.lang.Class 对象。
  • 加载.class文件的方式

    • 从本地系统中直接加载
    • 通过网络下载.class文件
    • 从zip,jar等归档文件中加载.class文件
    • 从专有数据库中提取.class文件
    • 将Java源文件动态编译为.class文件

验证

  • 任务:确保加载的字节码是合法的,符合 JVM 规范。
  • 验证内容
    1. 文件格式验证
      • 检查字节码文件是否符合 JVM 规范(如魔数、版本号等)。
    2. 元数据验证
      • 检查类的元数据是否合法(如是否有父类、是否继承了 final 类等)。
    3. 字节码验证
      • 检查方法体中的字节码指令是否合法,是否会危害 JVM。
    4. 符号引用验证
      • 检查类、方法、字段的引用是否存在且可访问。

准备

  • 任务:为类的静态变量分配内存,并设置默认初始值。

  • 具体行为

    • 静态变量会被分配内存并初始化为零值(如 int 初始化为 0boolean 初始化为 false)。
    • 如果是常量(static final),则直接赋值为指定的值。
  • 示例:

static int a = 10;  // 准备阶段:a = 0
static final int b = 20;  // 准备阶段:b = 20

解析

  • 任务:将常量池中的符号引用转换为直接引用。
  • 符号引用:一组符号描述引用目标(如类名、方法名)。
  • 直接引用:指向目标在内存中的指针或偏移量。
  • 解析内容
    • 类或接口的解析。
    • 字段的解析。
    • 方法的解析。

初始化

  • 任务:执行类的静态初始化代码(静态代码块和静态变量赋值)。
  • 触发条件
    • 创建类的实例(new)。
    • 访问类的静态变量或静态方法。
    • 使用反射加载类(如 Class.forName())。
    • 初始化子类时,父类会先被初始化。
static int a = 10;  // 初始化阶段:a = 10
static {
    System.out.println("Static block executed");
}

类加载器

JVM 通过类加载器来加载类。Java 中有以下三类类加载器:

image-20250217224811133

启动类加载器(Bootstrap ClassLoader)

  • 职责:加载 JVM 核心类库(如 java.lang.*java.util.* 等)。
  • 实现:由 JVM 自身实现,通常是用 C/C++ 编写的。
  • 路径:加载 JAVA_HOME/lib 目录下的类。

扩展类加载器(Extension ClassLoader)

  • 职责:加载扩展类库(如 javax.* 等)。
  • 实现:由 sun.misc.Launcher$ExtClassLoader 实现。
  • 路径:加载 JAVA_HOME/lib/ext 目录下的类。

应用程序类加载器(Application ClassLoader)

  • 职责:加载用户类路径(ClassPath)下的类。
  • 实现:由 sun.misc.Launcher$AppClassLoader 实现。
  • 路径:加载 -classpath-cp 指定的类。

自定义类加载器(User-Defined ClassLoader)

  • 职责:用户可以通过继承 ClassLoader 类实现自定义类加载器。
  • 用途
    • 热部署:在不重启 JVM 的情况下重新加载类。
    • 模块化加载:加载特定模块的类。
    • 加密类加载:加载加密的字节码文件。

双亲委派模型

双亲委派模型是类加载器之间的协作机制。

工作原理

  1. 当一个类加载器需要加载类时,它首先会委托给父类加载器加载。
  2. 如果父类加载器无法加载,子类加载器才会尝试加载。
  3. 最终,如果所有父类加载器都无法加载,才会抛出 ClassNotFoundException

优点

  • 安全性:防止用户自定义的类替换核心类(如 java.lang.String)。
  • 避免重复加载:确保类只被加载一次。

打破双亲委派

  • 在某些场景下(如 SPI 服务加载、模块化加载),可能需要打破双亲委派模型。
  • 安全性:防止用户自定义的类替换核心类(如 java.lang.String)。
  • 避免重复加载:确保类只被加载一次。

打破双亲委派

  • 在某些场景下(如 SPI 服务加载、模块化加载),可能需要打破双亲委派模型。
  • 例如:Thread.currentThread().setContextClassLoader() 可以设置线程上下文类加载器。

相关文章:

  • XSS攻击(跨站脚本攻击)详解与实战
  • 零基础入门机器学习 -- 第五章决策树与随机森林
  • BSD协议栈:多播
  • Visual Basic语言的数据类型
  • Logo语言的图形用户界面
  • jar命令解压jar包及更新jar的配置文件
  • RTMP(Real-Time Messaging Protocol)
  • 网工项目理论1.11 网络出口设计
  • seata基本使用
  • 【Java】Mongodb
  • UI自动化教程 —— 元素定位技巧:精确找到你需要的页面元素
  • Kafka偏移量管理全攻略:从基础概念到高级操作实战
  • 如何在yolov8系列运行自己的数据集
  • NAT(网络地址转换)技术详解:网络安全渗透测试中的关键应用与防御策略
  • 嵌入式人工智能应用-第四章 决策树 6
  • PostgreSQL 创建数据库
  • 一个基于Spring Boot和Vue.js的web商城系统-邻家小铺
  • SyntaxError: invalid syntax
  • MYSQL中的性能调优方法
  • Mac 安装Ollama和llama3,本地部署LobeChat和刘皇叔聊三国
  • 全国35城居民对公共服务满意度“打分”,上海多项指标居首
  • 改造老旧小区、建立“一张图”,五部委将多举措支持城市更新
  • 张核子“限高”次日即被解除,前员工的执行款3个月后仍未到账
  • 聚焦中华文明精神标识,多校专家学者跨学科对话交流
  • 体育文化赋能国际交流,上海黄浦举办国际友人城市定向赛
  • 网警打谣:传播涉刘国梁不实信息,2人被处罚