秋招Day11 - JVM - 类加载机制

了解类的加载机制吗?

JVM是运行Java字节码,也就是运行.class文件的虚拟机,JVM把.class文件中描述类的数据结构 加载到内存中,并对数据进行校验,解析和初始化 ,最终转化为JVM可以使用的类型(Klass),这个过程被称为类加载。

元空间(方法区)

├── ClassA的空间

│ ├── ClassA的Klass元数据

│ └── ClassA的运行时常量池

├── ClassB的空间

│ ├── ClassB的Klass元数据

│ └── ClassB的运行时常量池

└── ClassC的空间

├── ClassC的Klass元数据

└── ClassC的运行时常量池

其中最重要的三个概念:

  • 类加载器:负责加载class文件到内存中,生成Klass元数据结构
  • 类加载过程:包括加载、验证、准备、解析和初始化
  • 双亲委派模型:当一个类加载器收到类加载请求时,它会把请求委派为父类加载器进行,依次递归直到到达最顶层,如果父加载器无法完成请求,发出委托的子加载器才会尝试加载

类加载器有哪些?

  • 启动类加载器:负责加载JVM的核心类库
  • 外部类加载器:负责加载JAVA_HOME/jre/lib/ext目录下的类库
  • 应用程序类加载去:负责加载classpath下的类库
  • 用户自定义类加载器:负责加载网络上的类 、执行热部署 (动态加载 和替换应用程序的组件),通过继承ClassLoader类实现

说一下类的生命周期

加载 -> 连接(验证 -> 准备 -> 解析) -> 初始化 -> 使用 -> 卸载

类装载的过程了解吗?

包括载入,链接和初始化

  1. 载入:将class文件中的类的元数据 相关的数据结构信息装载到内存中
  2. 链接:
    1. 验证:验证类文件格式是否符合JVM规范
    2. 准备:为类的静态变量分配内存并赋默认值
    3. 解析:将符号引用替换为直接引用
  3. 初始化:执行静态代码块 和静态变量初始化

++载入过程JVM会做什么?++

  1. 通过类的全限定名来获取此类的二进制字节流
  2. 将二进制字节流中的有关类的元数据的静态信息转化为元空间中的Klass ,并创建运行时常量池
  3. 在堆中创建Class对象

为什么要用双亲委派模型?

  • 为了避免类的重复加载:父加载器加载的类,子类无需重复加载
  • 保证核心类库的安全:比如java.lang.*下面的类只能由启动类加载器加载,防止被篡改

如何破坏双亲委派机制?

重写ClassLoder的loadClass方法,不会委托给父类而是自己加载

如果重写findClass方法,并不会破坏双亲委派机制,而是自定义了自己的类加载机制

有哪些破坏双亲委派机制的典型例子?

++第一种:SPI加载JDBC驱动++

JDBC的核心SPI接口(如 java.sql.Driver)由 Bootstrap ClassLoader 加载。

但具体 的JDBC SPI的驱动实现(如 MySQL Connector/J, PostgreSQL JDBC Driver等)是由各数据库厂商提供的,通常放在应用程序的 classpath 下,由 Application ClassLoader 加载。

当 java.sql.DriverManager (由Bootstrap ClassLoader加载) 需要加载并注册具体的驱动实现时,父加载器加载的类对于子加载器是可见的,但父加载器Bootstrap 加载的类无法直接看到 Application ClassLoader 加载的类。

为了解决这个问题,JDBC使用了SPI机制。DriverManager 会使用线程上下文类加载器 (Thread Context ClassLoader) 来加载这些SPI实现 。线程上下文类加载器通常是 Application ClassLoader,这样就++允许了父加载器(Bootstrap)去请求子加载器(Application)加载类++ ,这实际上是双亲委派模型的一个"逆向"操作。

++第二种:热部署++

热部署是指在不重启应用程序的情况下更新代码,需要替换旧版本的类,但旧版本的类可能通过父加载器来加载,如果仍然保持父加载优先,那么可能会导致仍然返回旧的类版本 。为了解决上述问题,可以通过自定义类加载器加载替换的新类,并通过"子优先"优先加载类的新版本。

Tomcat的类加载机制了解吗?

  • Bootstrap ClassLoader:启动类加载器,加载Java的核心类库
  • Catalina ClassLoader:Tomcat核心类库加载器
  • Shared ClassLoader:共享类加载器,允许不同的Web应用程序共享某些类库
  • Webapp ClassLoader:应用程序类库加载器,支持多应用隔离 和优先加载应用自定义的类库 (破坏了双亲委派模型)。包括直接由该Web应用程序开发者编写的类和依赖库lib下的类

你认为应该怎样实现一个热部署功能?

热部署是指在不重启应用程序的情况下修改代码,动态加载、更新或卸载应用程序的组件,比如类、配置文件等。需要在类加载器的基础上实现类的重新加载。

  1. 首先通过WatchService来监控类文件和配置文件的变化,当检测到文件变更时,触发热部署流程。
  2. 然后创建一个自定义的类加载器,继承自ClassLoader,重写loadClass方法(子优先),以及findClass方法,用来加载新的类文件
相关推荐
silvamux_12 分钟前
Spring Boot 调用大模型 api 最小可跑教程
java·spring boot·后端
今年下半年15 分钟前
【Spring Boot 】通过 OpenFeign 请求第三方接口
java·spring boot·后端·openfeign
范什么特西24 分钟前
亲和路由(inspect)
java
她说可以呀27 分钟前
Docker 镜像的两种创建方式
java·分布式·docker
霸道流氓气质36 分钟前
AgentFlow 入门与实战:Task-Based 并发、EWMA 动态调度与四道门禁的 Java 生产级编排
java·开发语言
愿得一猪蹄1 小时前
# Java线程池实战,别再new Thread了
java
ee又momo1 小时前
# 深入理解Java注解,从使用到自定义
java
霸道流氓气质1 小时前
AI智能博客平台实战:RAG增强写作、多Agent协作与语义检索的Vue3 + Spring AI全栈实现
java·人工智能·spring
打工仔折腾 AI1 小时前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战
哦虎!2 小时前
【JavaEE】网络原理 - TCP/IP
java