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 等框架常采用此方式加载业务类。
相关推荐
牧天白衣.1 分钟前
02-基础语法
java
leo__5206 分钟前
MHT多假设跟踪算法(Multiple Hypothesis Tracking)MATLAB实现
开发语言·算法·matlab
燃于AC之乐6 分钟前
深入解剖STL RB-tree(红黑树):用图解带入相关复杂操作实现
开发语言·c++·stl·红黑树·大厂面试·图解·插入操作
dawudayudaxue7 分钟前
Eclipse安卓环境配置
android·java·eclipse
a1117768 分钟前
堆叠式流程图编辑器(html 开源)
开发语言·前端·javascript·开源·编辑器·html·流程图
iPadiPhone9 分钟前
性能优化的“双刃剑”:MySQL 查询缓存深度架构解析与面试复盘
java·后端·mysql·缓存·面试·性能优化
兆子龙9 分钟前
ahooks useDebounce 与 useThrottle:防抖节流的最佳实践
java·javascript
new code Boy14 分钟前
JavaScript转Python”的速查表
开发语言·javascript·python
老友@16 分钟前
云计算的统一心智模型
开发语言·ci/cd·docker·云计算·k8s·perl
Elnaij19 分钟前
从C++开始的编程生活(19)——set和map
开发语言·c++