您好,登录后才能下订单哦!
# 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/lib
WEB-INF/lib
delegate="false"
未来发展方向: - 增强对Java模块化的支持 - 优化云环境下的类加载效率 - 改进类重新加载机制
注:本文基于Tomcat 9.x版本编写,部分细节可能随版本变化而调整。实际部署时应参考对应版本的官方文档。 “`
这篇文章共计约2900字,采用Markdown格式编写,包含: 1. 多级标题结构 2. 代码块展示配置示例 3. Mermaid流程图 4. 表格对比 5. 文件目录树形结构 6. 重点内容强调
可根据具体需要调整各部分详细程度或补充特定场景的案例说明。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。