类加载器工作流程本质是“先查父、再自办”,通过双亲委派模型实现层级委托:启动类加载器(c++,加载核心类)、平台/扩展类加载器(java,加载扩展类)、系统类加载器(加载业务类),自定义加载器可插入链中;加载时先向上委派检查是否已加载,未命中则向下尝试加载;该模型保障安全性、类型一致性和避免冗余;热部署、osgi、动态字节码等场景需打破委派,通过重写loadclass或直接defineclass实现。

类加载器的工作流程本质是“先查父、再自办”,双亲委派模型不是指两个爹,而是强调“有事找上级”的委托逻辑——它用层级协作保障核心类不被篡改、避免重复加载、统一类型身份。
类加载器怎么分工协作
Java 默认有三层加载器,形成一条向上的委托链:
-
启动类加载器(Bootstrap):C++ 实现,加载
JAVA_HOME/jre/lib下的核心类(如java.lang.Object),无法在 Java 中直接引用,表现为null -
平台类加载器(Platform,JDK 9+)或扩展类加载器(Extension,JDK 8-):加载
lib/ext或模块系统中的扩展类,Java 实现,父加载器为 Bootstrap -
系统类加载器(System / Application):加载
classpath下的业务类,也是你写代码时默认使用的加载器,父加载器为 Platform/Extension
自定义加载器可插入该链任意位置,但需显式指定父加载器,否则默认以 System ClassLoader 为父。
双亲委派具体怎么走流程
当调用 loadClass("com.example.User") 时,并非立刻去磁盘找文件,而是按两阶段推进:
-
向上委派:Application → Platform → Bootstrap,每层都先检查自己是否已加载过该类(
findLoadedClass),已加载则直接返回;未加载且有父,则交上去 -
向下尝试:Bootstrap 在
rt.jar中没找到 → 返回给 Platform → Platform 在ext中没找到 → 返回给 Application → Application 在 classpath 中定位并加载User.class
整个过程是同步加锁的,防止多线程重复加载同一类。
为什么必须用这个模型
核心就三点:
-
安全性:用户无法用自己的
java.lang.String替换系统版本——因为请求一上来就被 Bootstrap 拦下并加载了正版 -
一致性:不同加载器加载的
Object是同一个 Class 对象,保证类型判断(instanceof)、强制转换、静态变量共享等行为可靠 - 避免冗余:父加载器已加载的类,子加载器不再重复解析和链接,节省内存与初始化开销
什么时候要打破委派
标准模型很稳健,但某些场景必须绕过:
- 热部署:Web 容器(如 Tomcat)需隔离各应用的类,每个应用用独立加载器,且优先用自己的版本,而非委派给系统加载器
- OSGi 插件:模块间需精细控制类可见性,依赖自定义委派策略(如先本地、再导入、最后父委派)
- 动态字节码:如 AOP 生成代理类,常由自定义加载器直接 defineClass,跳过 findClass 委派环节
打破方式很简单:重写 loadClass,去掉父委派调用,或在 findClass 中直接读取字节码并 define。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











