Java技术八股Day19

类加载器详解

类加载器核心概念

类加载器是负责加载类的对象,核心作用是将 Java 类的二进制字节流(.class 文件)动态加载到 JVM 中,在内存生成对应的 Class 对象作为访问入口。ClassLoader 是抽象类,除 BootstrapClassLoader 由 C++ 实现外,其余类加载器均由 Java 实现并继承自该类。每个类都持有加载它的类加载器引用,数组类由 JVM 自动创建,其类加载器与元素类型的类加载器一致(基本类型数组无类加载器)。类加载器遵循 "按需加载" 和 "相同二进制名称类仅加载一次" 规则,已加载的类会存储在自身的 classes 集合中。

JVM 内置类加载器

JVM 内置三种类加载器,按层级从高到低为:

  • BootstrapClassLoader(启动类加载器):顶层加载器,C++ 实现,无父加载器,加载 JDK 核心类库(% JAVA_HOME%/lib 目录下的 rt.jar 等)及 -Xbootclasspath 指定路径的类,获取其引用时返回 null。
  • ExtensionClassLoader(扩展类加载器):加载 % JRE_HOME%/lib/ext 目录及 java.ext.dirs 系统变量指定路径的类,父加载器为 BootstrapClassLoader。
  • AppClassLoader(应用程序类加载器):面向用户,加载当前应用 classpath 下的类,父加载器为 ExtensionClassLoader,是用户自定义类的默认加载器。Java9 后扩展类加载器更名为平台类加载器,除 java.base 等核心模块由启动类加载器加载外,其他模块由其加载。

自定义类加载器

自定义类加载器需继承 ClassLoader 抽象类,推荐重写 findClass () 方法(不打破双亲委派模型),仅在父类加载器无法加载时,通过该方法自定义字节流获取逻辑(如解密加密的 .class 文件);若需打破双亲委派模型,则需重写 loadClass () 方法,改变 "先委派父类加载" 的默认流程。自定义类加载器的父加载器可通过构造函数指定,可是内置类加载器或其他自定义类加载器,通过组合关系复用父加载器逻辑。

双亲委派模型

(1)核心定义

双亲委派模型是 JDK 推荐的类加载机制,要求除顶层启动类加载器外,所有类加载器都有父加载器,类加载请求会先委派给父加载器执行,仅当父加载器无法加载时,子加载器才尝试自己加载。此处 "双亲" 并非指两个父加载器,而是层级委派关系,父子关系通过组合实现而非继承。

(2)执行流程
  1. 类加载时先检查当前类是否已加载,已加载则直接返回;
  2. 未加载则将请求委派给父加载器,最终传递至 BootstrapClassLoader;
  3. 父加载器尝试加载,若成功则返回 Class 对象,失败则子加载器调用 findClass () 方法自行加载;
  4. 若子加载器也无法加载,抛出 ClassNotFoundException 异常。
(3)核心好处
  • 避免类重复加载:同一类由父加载器统一加载,确保类的唯一性;
  • 保护核心 API:核心类(如 java.lang.Object)由 BootstrapClassLoader 加载,且 ClassLoader 的 preDefineClass () 方法禁止加载以 "java." 开头的类,防止恶意篡改核心类。

打破双亲委派模型的方式

双亲委派模型非强制性约束,打破方式主要有两种:

  • 重写 loadClass () 方法:自定义类加载器重写该方法,改变 "先委派父加载" 的逻辑,例如 Tomcat 的 WebAppClassLoader,优先加载 Web 应用目录下的类,实现 Web 应用间类隔离;
  • 利用线程上下文类加载器:通过 Thread 的 setContextClassLoader () 设置上下文类加载器,让高层类加载器(如加载 SPI 接口的 BootstrapClassLoader)借助低层类加载器(如加载 SPI 实现的 AppClassLoader)加载类,解决 SPI 接口与实现类加载层级不一致的问题,Spring 等框架常采用此方式加载业务类。
相关推荐
彧azz13 小时前
图的存储结构详解:邻接矩阵的原理、实现与应用
开发语言·数据结构·学习·php
IT_Octopus13 小时前
IntelliJ 本地日志路径自定义:`-DLOG_PATH=./logs` 为什么总“不听话“
java·log4j·intellij-idea
嵌入式学习菌14 小时前
Modbus‑RTU 数据类型分析
开发语言·单片机·bug
长征coder14 小时前
【无标题】
java·性能优化
matlab代码15 小时前
基于matlab数字图像处理的指纹识别系统【源码68期】
开发语言·matlab
新时代牛马15 小时前
PCI与PCIe 硬件原理、配置空间/BAR 与 Linux 驱动完整篇:从 LTSSM、TLP 到 ECAM 与probe
java·linux·服务器
Bs_MoneyMagnet15 小时前
基于springboot+vue的医疗健康便民服务平台的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring
matlab代码15 小时前
基于matlab的水果识别系统(苹果香蕉菠萝梨桃子)【源码65期】
开发语言·matlab
wuyk55515 小时前
从零吃透 MQTT 通信|第 8 章 FreeRTOS 多任务架构下 MQTT 工程架构,任务拆分、队列解耦、临界区保护
c语言·开发语言·stm32·学习·架构
weixin1997010801615 小时前
[特殊字符]《跨境二手ERP对接Back Market:标准化API + 7~10工作日技术合规审核实录》(附Python源码)
开发语言·python·pandas