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 等框架常采用此方式加载业务类。
相关推荐
阿维的博客日记40 分钟前
Hippo4j 线程池监控平台部署手册
java·spring boot·后端
南境十里·墨染春水2 小时前
C++ 工厂模式:从入门到进阶,彻底掌握对象创建的艺术
开发语言·c++·算法
C+++Python3 小时前
详细介绍一下Java泛型的通配符
java·windows·python
JosieBook4 小时前
【数据库】时序预测能力的分级进化:TimechoAI如何让每一类用户都能精准预见未来
java·开发语言·数据库
加号34 小时前
【C#】 文件与目录管理:创建、删除操作的技术解析
开发语言·c#
diving deep4 小时前
脚本速览-python
开发语言·python
一生了无挂4 小时前
Java处理JSON技巧教学(从基础到高阶实战全覆盖)
java·开发语言·json
李白的天不白5 小时前
使用 SmartAdmin 进行前后端开发
java·前端
swordbob5 小时前
Spring 单例 Bean 是线程安全的吗?
java·开发语言
2601_951643776 小时前
Python第一,Java跌出前三,C语言杀回来了
java·c语言·python·编程语言排行·技术趋势