详情可以参考:https://tomcat.apache.org/tomcat-10.1-doc/class-loader-howto.html
简要说明
Tomcat安装了多种类加载器,以便容器的不同部分、容器中的应用访问能够不同的类和资源。
在Java环境中,类加载器被组织为父-子树的形式。通常情况下,如果一个类加载器被要求加载一个类或者资源,它会先委托它的父类加载器去寻找并加载,如果父类加载器没有找到要加载的类或者资源,类加载器才会从它自身的库中去寻找。但是,web应用的类加载器默认与此委托模型不同。
当Tomcat启动的时候,创建如下父子关系的类加载器,其中上面是父、下面是子:
(图形来自Tomcat官网:https://tomcat.apache.org/tomcat-10.1-doc/class-loader-howto.html)
如果还启用了Server 或/和 Shared类加载器,会是下面的形式:
类加载器的定义
Bootstrap类加载器
Bootstrap加载Java虚拟机提供的基本运行时类、及来自系统扩展目录($JAVA_HOME/jre/lib/ext)下面JAR文件中的类。
System类加载器
System正常是加载CLASSPATH 环境变量下面的类。加载的这些类对Tomcat的内部类和web应用可见。但是,标准的Tomcat启动脚本($CATALINA_HOME/bin/catalina.sh 或者 %CATALINA_HOME%\bin\catalina.bat
)完全忽略CLASSPATH环境变量的内容,而是从下面的库中加载类:
$CATALINA_HOME/bin/bootstrap.jar
$CATALINA_BASE/bin/tomcat-juli.jar 或者$CATALINA_HOME/bin/tomcat-juli.jar
$CATALINA_HOME/bin/commons-daemon.jar
Common类加载器
Common加载另外的一些类,这些类对Tomcat的内部类和所有web应用可见。Common类加载器搜索的位置在$CATALINA_BASE/conf/catalina.properties
文件中用属性common.loader
定义。通常,应用的类不应该放在这里。
common.loader="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
Common类加载器默认按照顺序搜索如下位置:
$CATALINA_BASE/lib下面没有打包的类和资源
$CATALINA_BASE/lib下面的JAR文件
$CATALINA_HOME/lib下面没有打包的类和资源
$CATALINA_HOME/lib下面的JAR文件
WebappX类加载器
WebappX:Tomcat为容器中的每个web应用创建一个类加载器。这个类加载器加载web应用下面 /WEB-INF/classes
目录下面没有打包的类和资源、 /WEB-INF/lib
目录下面JAR文件中的类和资源。这些类和资源仅对该web应用可见,对其它web应用不可见。
这个加载器先自己加载,而不把加载请求委托给父类加载器,这一点与其它类加载器不同。当然,还是有一些例外的,例如:属于JRE的基类部分的不能被覆盖、对于Tomcat 实现的Jakarta EE API类总是先委托(Servlet, JSP, EL, WebSocket)
从web应用的角度来看,类和资源加载按照下面的位置顺序查找:
1)Java虚拟机的Bootstrap类
2)web应用的/WEB-INF/classes
目录
3)web应用的/WEB-INF/lib/*.jar
4)System类加载器加载的类
5)Common 类加载器加载的类
如果 web应用类加载器使用 <Loader delegate="true"/>
属性配置(https://tomcat.apache.org/tomcat-10.1-doc/config/loader.html),查找位置顺序变为如下:
1)Java虚拟机的Bootstrap类
2)System类加载器加载的类
3)Common 类加载器加载的类
4)web应用的/WEB-INF/classes
目录
5)web应用的/WEB-INF/lib/*.jar
Server类加载器
Server类加载器:这个类加载器只对Tomcat内部类可见,对web应用完全不可见。搜索位置在conf/catalina.properties
文件中用server.loader
属性定义。
Shared 类加载器
Shared 类加载器:对所有web应用可见。搜索位置在conf/catalina.properties
文件中用shared.loader
属性定义。这通常用来在所有web应用之间共享代码。但是,对这些被加载的类的更新,需要Tomcat重启才能生效。