秋招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方法,用来加载新的类文件
相关推荐
青云交14 分钟前
Java 大视界 -- Java 大数据在智能医疗电子病历数据分析与临床决策支持中的应用(382)
java·大数据·数据分析·flink·电子病历·智能医疗·临床决策
麦兜*15 分钟前
国产大模型平替方案:Spring Boot通义千问API集成指南
java·spring boot·后端·python·spring cloud·系统架构·springboot
菜鸟的迷茫18 分钟前
Spring Cloud Resilience4j 实战:熔断、限流、隔离、降级全流程详解
java·后端
le16161620 分钟前
Groovy学习篇章一之—— GDK 探秘:Groovy如何给Java对象“开外挂”,让String也能“跑命令”!
android·java·学习
桦说编程26 分钟前
CompletableFuture 的第四种调用模式
java·性能优化·函数式编程
顽疲29 分钟前
从零用java实现小红书springboot_vue_uniapp(15)评论和im添加图片
java·vue.js·spring boot·uni-app
im_AMBER44 分钟前
Leetcode 13 java
java·算法·leetcode
贰拾wan1 小时前
SpringBoot自动装配原理
java·spring boot·spring
美团快速送达1 小时前
每日一题----第四题
java·算法·leetcode