双亲委派模型是类加载的协作规则,非强制协议:先查缓存,再委托父加载器(直至bootstrap),最后才由当前加载器调用findclass;java 17起分为bootstrap、platform、app三层加载器;核心意义在于防篡改、保唯一、稳依赖;可打破但需正当理由。

双亲委派模型不是“两个父母”,而是“先找父加载器,父搞不定再自己来”。它本质是类加载的协作规则,不是强制协议,但 JVM 内置加载器默认严格遵循,目的是让核心类稳如磐石、业务类各安其位。
工作流程:向上委托 → 自上而下尝试 → 逐级回落
当某个类加载器(比如你写的自定义加载器)收到 loadClass("com.example.Service") 请求时,实际执行分三步:
- 先查缓存:检查自己是否已加载过该类(避免重复加载),有则直接返回 Class 对象;
-
再往上交:调用
parent.loadClass(),把请求递交给父加载器;这个动作会一路向上,直到启动类加载器(Bootstrap); -
最后才动手:只有当所有上级都返回
null(即找不到该类),当前加载器才调用findClass()从自己的路径(如 jar、文件系统)中读取字节码并 define。
类加载器层级:Java 17 起已简化为三层
不再有“扩展类加载器”这个独立角色,取而代之的是更清晰的平台级划分:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
启动类加载器(Bootstrap):C++ 实现,加载
java.base等核心模块(String、Object等),无 Java 对象,getClassLoader()返回null; -
平台类加载器(Platform):替代旧版 Extension,加载
java.sql、java.xml等 JDK 平台模块; -
应用类加载器(App / System):加载 classpath 或模块路径下的业务代码,默认线程上下文类加载器(
Thread.currentThread().getContextClassLoader()); -
自定义类加载器:继承
ClassLoader,父加载器默认是 App 类加载器,可重写findClass()实现热部署、插件隔离等场景。
核心意义:安全、唯一、可预测
这机制不是为了炫技,而是解决三个关键问题:
-
防篡改:确保
java.lang.Integer永远由 Bootstrap 加载——你哪怕在 classpath 放一个同名类,也不会被 App 加载器加载,杜绝恶意替换核心类; -
保唯一:同一全限定名的类,在整个 JVM 中只被一个加载器加载一次,避免因不同加载器重复加载导致
ClassCastException(比如两个MyService类虽字节码相同,但因加载器不同而视为不同类型); -
稳依赖:上层类(如你自己写的 Service)引用
java.util.List,必然通过 Bootstrap 加载,不会因某插件自带低版本 List 而引发冲突,保障运行时行为可预期。
打破它?可以,但得有正当理由
双亲委派不是铁律。JDBC 的 DriverManager 就主动打破——它用线程上下文类加载器(通常是 App 加载器)去加载用户注册的驱动类(如 com.mysql.cj.jdbc.Driver),因为 Bootstrap 根本看不到这些第三方类。类似场景还有 OSGi、Tomcat 的 webapp 隔离、Spring Boot 的 DevTools 热重启。打破方式通常是绕过 loadClass(),直接在子类中调用 findClass() 或使用上下文类加载器。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










