您好,登录后才能下订单哦!
# Tomcat类加载的架构及存放目录
## 1. Tomcat类加载机制概述
Apache Tomcat作为广泛使用的Java Web应用服务器,其类加载机制设计具有独特的层次结构。与传统的Java类加载模型不同,Tomcat通过自定义的类加载器实现了应用隔离、资源隔离和灵活部署等关键特性。
### 1.1 与JVM类加载器的区别
标准JVM类加载器采用双亲委派模型,包含以下层次:
- Bootstrap ClassLoader(加载JRE核心类)
- Extension ClassLoader(加载JRE扩展类)
- Application ClassLoader(加载应用类)
而Tomcat在此基础上进行了扩展,主要差异体现在:
1. 打破了严格的双亲委派模式
2. 增加了Web应用级别的隔离
3. 支持热部署时的类重新加载
### 1.2 Tomcat类加载器的核心目标
1. **应用隔离**:不同Web应用间的类互不可见
2. **资源共享**:公共类库(如Servlet API)只需加载一次
3. **安全性**:防止应用覆盖容器核心类
4. **灵活性**:支持单个应用的重载而不影响其他应用
## 2. Tomcat类加载器架构
### 2.1 类加载器层次结构
Tomcat 9.x的完整类加载器体系:
Bootstrap ↑ Extension ↑ System ↑ Common ↑ ├── WebApp (每个Web应用独有) └── Jasper (JSP编译使用)
### 2.2 关键类加载器详解
#### 2.2.1 Common ClassLoader
- **父加载器**:System ClassLoader
- **加载路径**:`$CATALINA_HOME/lib/*.jar`
- **职责**:
  - 加载Tomcat容器和所有Web应用的共享类
  - 包含Servlet API、JSP API等基础库
  - 可通过`catalina.properties`中的`common.loader`配置
#### 2.2.2 WebApp ClassLoader
- **父加载器**:Common ClassLoader
- **加载路径**:
  - `/WEB-INF/classes`
  - `/WEB-INF/lib/*.jar`
- **特性**:
  - 每个Web应用独立实例化
  - 默认开启`delegate`模式(先委托父加载器)
  - 支持热部署时的类重新加载
#### 2.2.3 Jasper ClassLoader
- **用途**:专门用于JSP页面的编译
- **生命周期**:仅在JSP编译期间存在
- **特点**:
  - 高频创建和销毁
  - 隔离编译产生的临时类
### 2.3 类加载顺序流程图
```mermaid
graph TD
    A[WebApp ClassLoader] -->|1. 委托| B[Common ClassLoader]
    B -->|2. 委托| C[System ClassLoader]
    C -->|3. 委托| D[Extension ClassLoader]
    D -->|4. 委托| E[Bootstrap ClassLoader]
    A -->|5. 自行加载| F[/WEB-INF/classes]
    A -->|6. 自行加载| G[/WEB-INF/lib/*.jar]
$CATALINA_HOME/
├── bin/            # 启动脚本
├── conf/           # 全局配置
├── lib/            # Common ClassLoader加载位置
│   ├── catalina.jar
│   ├── servlet-api.jar
│   └── ...
├── webapps/        # 应用部署目录
│   ├── ROOT/       # 默认应用
│   ├── app1/       # 示例应用1
│   │   ├── WEB-INF/
│   │   │   ├── classes/   # 应用类文件
│   │   │   └── lib/       # 应用依赖JAR
│   └── app2/       # 示例应用2
└── work/           # 运行时生成文件
    ├── Catalina/   # 引擎相关
    │   └── localhost/ # 虚拟主机
    │       ├── app1/  # JSP编译结果
    │       └── app2/
    └── ...         
WEB-INF/
├── classes/       # 编译后的类文件
│   ├── com/       # 包结构
│   │   └── example/
│   │       └── MyServlet.class
├── lib/           # 应用依赖库
│   ├── utils.jar
│   └── jdbc-driver.jar
└── web.xml        # 部署描述符
Manager应用清理在conf/catalina.properties中:
# Common类加载器路径配置
common.loader="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
# 是否启用类加载器委托
tomcat.util.scan.StandardJarScanFilter.jarsToSkip=*.jar
通过context.xml配置:
<Context>
    <!-- 默认true,优先委托父加载器 -->
    <Loader delegate="true"/>
    
    <!-- 控制JAR扫描行为 -->
    <JarScanner scanClassPath="false"/>
</Context>
策略对比:
| 参数值 | 加载顺序 | 适用场景 | 
|---|---|---|
| true | 父优先 | 生产环境(安全) | 
| false | 本地优先 | 开发调试 | 
现象:相同类被不同加载器加载
解决:
1. 将冲突类移至$CATALINA_HOME/lib
2. 确保所有应用使用相同版本库
典型场景: - WebApp ClassLoader未被回收 - 静态成员持有类加载器引用
检测工具:
- JDK Mission Control
- Tomcat的LeakPreventionListener
随着JPMS引入的变化:
- 自动模块名称处理
- 模块路径与类路径的协调
- jlink自定义运行时支持
JVM参数添加:-verbose:class
<Resources cachingAllowed="true" cacheMaxSize="102400"/>
推荐部署方案:
$CATALINA_HOME/libWEB-INF/libdelegate="false"未来发展方向: - 增强对Java模块化的支持 - 优化云环境下的类加载效率 - 改进类重新加载机制
注:本文基于Tomcat 9.x版本编写,部分细节可能随版本变化而调整。实际部署时应参考对应版本的官方文档。 “`
这篇文章共计约2900字,采用Markdown格式编写,包含: 1. 多级标题结构 2. 代码块展示配置示例 3. Mermaid流程图 4. 表格对比 5. 文件目录树形结构 6. 重点内容强调
可根据具体需要调整各部分详细程度或补充特定场景的案例说明。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。