java类加载器及tomcat为什么不用双亲委派

Java的类加载器体系以及Tomcat为何打破双亲委派模型,是理解Java类隔离机制和Web容器设计的关键。下面分别进行解释。


一、Java 类加载器与双亲委派模型

1. 类加载器层次结构

Java 默认提供了三个主要类加载器:

  • 启动类加载器(Bootstrap ClassLoader) :C++实现,负责加载<JAVA_HOME>/lib目录下的核心类库(如rt.jar),是所有类加载器的父类。
  • 扩展类加载器(Extension ClassLoader) :Java实现,负责加载<JAVA_HOME>/lib/ext目录下的扩展类库,父加载器为Bootstrap。
  • 应用类加载器(Application ClassLoader) :也称系统类加载器,负责加载用户类路径(ClassPath)下的类,父加载器为Extension。

2. 双亲委派模型的工作机制

当一个类加载器收到类加载请求时,它会先委托父加载器去加载 ,如果父加载器无法加载(抛出ClassNotFoundException),才由自己尝试加载。流程如下:

text

复制代码
请求 → 当前加载器 → 委派给父加载器 → ... → 最终到达Bootstrap
→ 若Bootstrap无法加载 → 逐级回退,由子加载器尝试加载

3. 为什么采用双亲委派?

  • 安全性 :防止用户自定义的类替换核心API(如java.lang.Object)。因为双亲委派会优先让Bootstrap加载,保证了核心类库的统一性。
  • 避免重复加载:确保同一个类在全系统中只被加载一次。

4. 加载过程?

类加载器负责将.class文件加载到JVM中,整个过程包括 加载(Loading)→ 连接(Linking)→ 初始化(Initialization) 三个主要阶段,其中连接又细分为 验证(Verification)→ 准备(Preparation)→ 解析(Resolution)


二、Tomcat 为什么要打破双亲委派?

Tomcat作为Web容器,需要同时部署多个Web应用,每个应用可能依赖不同版本的第三方库(如A应用使用Spring 4,B应用使用Spring 5),同时还要保证这些应用之间完全隔离 ,并且共享一些基础类库(如Servlet API、JSP API等)。如果完全遵循双亲委派,会导致以下问题:

  1. 无法隔离应用:在双亲委派下,所有应用的类都会由相同的AppClassLoader或其父加载器加载,不同应用的同名类(但版本不同)会发生冲突。
  2. 无法实现热部署:当重新部署一个应用时,需要卸载该应用的类。双亲委派中类一旦被父加载器加载,就无法被卸载。

因此,Tomcat必须打破双亲委派,自定义类加载器来满足Web容器的特殊需求。


三、Tomcat 的类加载器体系与打破机制

Tomcat设计了一套层次化的类加载器结构(以Tomcat 8为例):

text

scss 复制代码
Bootstrap
    │
    └── System (AppClassLoader)
            │
            └── Common
                    ├── Catalina
                    └── Shared
                            └── WebApp (每个Web应用一个实例)
  • Common :加载$CATALINA_BASE/lib下的公共类库,供Tomcat服务器和所有Web应用共享。
  • Catalina :加载Tomcat服务器内部实现所需的类(如catalina.jar),对Web应用不可见。
  • Shared:加载所有Web应用共享的类库(如自定义的公共库),对Tomcat服务器内部不可见。
  • WebApp :每个Web应用拥有独立的WebAppClassLoader,负责加载/WEB-INF/classes和/WEB-INF/lib下的类。

Tomcat 如何打破双亲委派?

WebAppClassLoader 打破了传统的双亲委派顺序:它首先尝试自己加载 (即加载/WEB-INF/classes和/WEB-INF/lib下的类),如果找不到,才委托父加载器(通常是Shared)加载。这样做的目的是:

  • 优先加载应用自身的类,实现应用之间的隔离。如果A应用和B应用有同名但不同版本的类,各自的WebAppClassLoader会独立加载,互不影响。
  • 仍允许共享某些基础类:当应用自身的类加载不到时,仍然可以向上委托,让Common或System加载JDK和Tomcat的基础类(如Servlet API),避免重复加载。

这种策略可以总结为:先自加载,后委派,与标准的双亲委派(先委派后自加载)正好相反。

其他打破点

  • Catalina 和 Shared 也打破了双亲委派吗?它们通常遵循标准的双亲委派,因为Tomcat需要确保内部实现(Catalina)不会被Web应用意外覆盖。只有WebAppClassLoader是主要打破点。

四、为什么Tomcat可以打破双亲委派?

双亲委派模型是Java官方推荐的实现,但并非强制约束 。ClassLoader类允许子类重写loadClass()方法,从而改变加载顺序。Tomcat正是通过自定义类加载器(WebappClassLoader)重写了loadClass(),实现了优先自加载的逻辑。


五、总结

对比点 标准双亲委派 Tomcat WebAppClassLoader
加载顺序 先委托父类,后自加载 先自加载,后委托父类
目的 安全性、避免重复加载 应用隔离、支持热部署
类冲突 不允许同名类存在 允许不同应用有同名不同版本类

Tomcat打破双亲委派,本质是在隔离性与共享性之间找到平衡:既要让每个Web应用拥有独立的类空间,又要保证基础类库(如JDK、Servlet API)被所有应用共享,从而节省内存、避免冲突。这一设计也成为了其他Java Web容器(如Jetty、Undertow)的通用实践。

相关推荐
AntsData7 小时前
用 12K+ 条亚马逊评论信号,定位机械键盘下一版该改什么
java·大数据·计算机外设
code2cat7 小时前
【随笔】连续批处理:长短请求怎样在迭代之间补位
java·人工智能·后端·大语言模型·vllm
最强小杰7 小时前
DeepSeek V4 Flash + Codex CLI 接入教程:原生 Responses API 适配,从配置到跑通收藏这篇就够了(2026)
java·前端·python·ai
Flynn Liang7 小时前
Spring AI 2.0 深度解析:ChatClient、Advisor 链与 MCP——Java 工程师的 AI 落地最优解
java·人工智能·spring·大模型·架构设计·spring ai
灿飞7 小时前
Kotlin与Java虚拟机六:基础与类型系统:一切皆对象,但对象有代价
java·kotlin
计算机毕设定制辅导-无忧学长7 小时前
《基于微信小程序健康习惯激励系统设计与实现》
java·spring boot·mysql·微信小程序·uniapp·健康习惯激励系统
雪芽蓝域zzs8 小时前
第 1 章:IDEA 创建 SpringBoot3.5.16 Maven 项目
java·maven·intellij-idea
golang学习记8 小时前
IDEA 开始换芯,发布全新AI版终端
java·人工智能·intellij-idea
vipxieliang8 小时前
ValidX 正则表达式预编译优化:Pattern 复用策略
java·spring boot·后端
Wang's Blog9 小时前
Java 项目实战:交友项目 - FastDFS 工作原理
java·大数据·交友