Tomcat类加载器
类加载器功能及作用
| 类加载器 | 作用 |
|---|---|
| 引导类加载器BootstrapClassLoader | c++编写,加载java核心库 java.*,比如rt.jar中的类,构造ExtClassLoader和AppClassLoader |
| 扩展类加载器ExtClassLoader | java编写,加载扩展库 JAVA_HOME/lib/ext目录下的jar 中的类,如classpath中的jre ,javax.*或者java.ext.dir 指定位置中的类 |
| 系统类加载器SystemClassLoader/AppClassLoader | 默认的类加载器,搜索环境变量 classpath 中指明的路径 |
- 引导类加载器 和 扩展类加载器 的作用不变
- 系统类加载器正常情况下加载的是 CLASSPATH 下的类,但是 Tomcat 的启动脚本并未使用该变 量,而是加载tomcat启动的类,比如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定。 位于CATALINA_HOME/bin下
- CommonClassLoader、CatalinaClassLoader、SharedClassLoader和WebappClassLoader是Tomcat自己定义的类加载器,它们分别加载/common/、/server/、/shared/*(在tomcat 6之后已经合并到根目录下的lib目录下)和/WebApp/WEB-INF/*中的Java类库。其中WebApp类加载器和Jsp类加载器通常会存在多个实例,每一个Web应用程序对应一个WebApp类加载器,每一个JSP文件对应一个Jsp类加载器。
- commonLoader:Tomcat最基本的类加载器,加载Tomcat使用以及应用通用的一些类,位于CATALINA_HOME/lib下, 比如servlet-api.jar,加载路径中的class可以被Tomcat容器本身以及各个Webapp访问;
- catalinaLoader:Tomcat容器私有的类加载器,用于加载服务器内部可⻅类,这些类应用程序不能访问,加载路径中的class对于Webapp不可见;
- sharedLoader:各个Webapp共享的类加载器,用于加载应用程序共享类,这些类服务器不会依赖,加载路径中的class对于所有Webapp可见,但是对于Tomcat容器不可见;
- WebappClassLoader:各个Webapp私有的类加载器,每个应用程序都会有一个独一无二的Webapp ClassLoader,他用来加载 本应用程序 /WEB-INF/classes 和 /WEB-INF/lib 下的类。加载路径中的class只对当前Webapp可见;
- 从上图的委派关系可以看出
CommonClassLoader能加载的类都可以被Catalina ClassLoader和SharedClassLoader使用,从而实现了公有类库的共用,而CatalinaClassLoader和Shared ClassLoader自己能加载的类则与对方相互隔离。
WebAppClassLoader可以使用SharedClassLoader加载到的类,但各个WebAppClassLoader实例之间相互隔离。
而JasperLoader的加载范围仅仅是这个JSP文件所编译出来的那一个.Class文件,它出现的目的就是为了被丢弃:当Web容器检测到JSP文件被修改时,会替换掉目前的JasperLoader的实例,并通过再建立一个新的Jsp类加载器来实现JSP文件的HotSwap功能。
- tomcat 8.5 默认改变了严格的双亲委派机制,当应用需要到某个类时,则会按照下面的顺序进行类加载:
- 使用bootstrap引导类加载器加载
- 如果未加载到,使用system系统类加载器加载,主要是为了防止一些基础类会被web中的类覆盖,如果加载到即返回。
- 如果未加载到,使用应用类加载器在WEB-INF/classes中加载
- 如果未加载到,使用应用类加载器在WEB-INF/lib中加载
- 最后还是加载不到的话,则委托父类加载器(Common ClassLoader)去加载。(在这最后一步,遵从双亲委派 机制)
- tomcat中类的加载如下图:
- 1 Bootstrap 引导类加载器
加载JVM启动所需的类,以及标准扩展类(位于jre/lib/ext下)
- 2 System 系统类加载器
加载tomcat启动的类,比如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定。位于CATALINA_HOME/bin下。
- 3 Common 通用类加载器
加载tomcat使用以及应用通用的一些类,位于CATALINA_HOME/lib下,比如servlet-api.jar
- 4 webapp 应用类加载器
每个应用在部署后,都会创建一个唯一的类加载器。该类加载器会加载位于 WEB-INF/lib下的jar文件中的class 和 WEB-INF/classes下的class文件。
双亲委派机制
什么是双亲委派机制
- 当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的上级类加载器,递归这个操
作,如果上级的类加载器没有加载,自己才会去加载这个类。
双亲委派机制的作用
- 防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。
- 保证核心.class不能被篡改。通过委托方式,不会去篡改核心.class,即使篡改也不会去加载,即使 加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个.class对象。这样 保证了class执行安全(如果子类加载器先加载,那么我们可以写一些与java.lang包中基础类同名 的类, 然后再定义一个子类加载器,这样整个应用使用的基础类就都变成我们自己定义的类了。)
- java类加载过程如下