Tomcat的类加载机制

Tomcat类加载分为四部分(不是步骤):
1.BootStrap 启动类加载
2.System 系统类加载 CATALINA_HOME/conf
3.Common 通用类加载 CATALINA_HOME/lib
4.Webapp 应用类加载 WEB-INF/lib和WEB-INF/classes

当Tomcat启动时,步骤如下:
1.BootStrap,加载JVM运行基本的类,以及标准扩展类(jre/lib/ext中的类)
2.System,加载catalina.bat/catalina.sh中指定位置的类,如bootstrap.jar、tomcat-juli.jar等
3.Webapp,每个应用在部署后,都会创建一个唯一的类加载器,该类加载器会加载位于WEB-INF/lib下的jar文件和WEB-INF/classes下的class文件(先classes文件夹再lib文件夹)
4.Common,加载Tomcat使用以及应用通用的一些类,位于CATALINA_HOME/lib下,比如servlet-api.jar

Tomcat中通过扩展URLClassLoader来实现自己的类加载器

Tomcat作为一个java web容器,也有自己的类加载机制,通过自定义的类加载机制以实现共享类库的抽取、不同web应用之间的资源隔离和热加载等功能。除了一些java自身的类加载器之外,Tomcat实现的主要类加载器有:Common ClassLoader、Catalina ClassLoader、Shared ClassLoader以及WebApp ClassLoader。

其中,Common、Catalina、Shared类加载器是URLClassLoader类的一个实例,只是它们的类加载路径不一样,在catalina.properties配置文件中进行配置(common.loader、server.loader、shared.loader)。

WebAppClassLoader继承自WebAppClassLoaderBase,基本所有的逻辑都在WebAppClassLoaderBase中实现了。

而WebAppClassLoaderBase、ExtClassLoader、AppClassLoader都继承自URLClassLoader,因此可以看出,Tomcat所有的类加载器都以URLClassLoader为基础进行扩展。

在默认配置中,Common、Catalina、Shared类加载器都是同一个对象,即commonLoader(因为Catalina、Shared的默认加载路径为空,直接返回父类加载器commonLoader)

一个Web应用对应着一个StandardContext实例,每个web应用都拥有独立的web应用类加载器(WebAppClassLoader),这个类加载器在StandardContext.startInternal()中被构造出来

Tomcat的类加载机制违反了双亲委托原则,对于一些未加载的非基础类(Object、String等),各个web应用自己的类加载器会优先加载,加载不到再交给commonClassLoader走双亲委托,针对某个类的具体加载逻辑位于WebAppClassLoaderBase.loadClass()方法中:
1.先在本地缓存中查找是否已经加载过该类(对于一些已经加载了的类,会被缓存在resourceEntries这个数据结构中),如果已经加载就返回;
2.让系统类加载器(AppClassLoader)尝试加载该类,主要是为了防止一些基础类会被web中的类覆盖,如果加载到就返回;
3.前两步都没加载到目标类,那么web应用的类加载器将自行加载(先加载WEB-INF/classes再加载WEB-INF/lib),如果加载到就返回;
4.最后还是加载不到的话,委托父类加载器(Common ClassLoader)去加载。

第3第4两个步骤的顺序已经违反了双亲委托机制,除了Tomcat外,JDBC、JNDI、Thread.currentThread().setContextClassLoader()等都一样违反了双亲委托。

另外,开发者也会因为粗心而犯下面的错误:
1.在CATALINA_HOME/lib以及WEB-INF/lib中放置了不同版本的jar包,此时就会导致某些情况下报加载不到类的错误;
2.如果多个应用使用同一jar包文件,当放置了多份,就可能导致多个应用间出现类加载不到的错误

原文地址:https://www.cnblogs.com/yuanfei1110111/p/10136801.html

时间: 2024-10-07 07:02:07

Tomcat的类加载机制的相关文章

深入剖析tomcat的类加载机制

1JVM类加载机制 JVM的ClassLoader通过Parent属性定义父子关系,可以形成树状结构.其中引导类.扩展类.系统类三个加载器是JVM内置的. 它们的作用分别是: 1)引导类加载器:使用native代码实现,在rt.jar等包中搜索运行JVM所需的类,例如java.lang等包下的类. 2)扩展类加载器:负责载入标准扩展目录中的类,例如Sun的JVM的扩展目录是/jdk/jre/lib/ext. 3)系统类加载器:默认的类加载器,搜索环境变量CLASSPATH中指明的路径. 2双亲委

【Tomcat】Tomcat的类加载机制

在Tomcat中主要有以下几种类加载器:(图片来自网络) tomcat启动时,会创建几种类加载器: 1 Bootstrap 引导类加载器 加载JVM启动所需的类,以及标准扩展类,位于jre/lib/ext下. 2 System 系统类加载器 加载tomcat启动的类,比如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定.位于CATALINA_HOME/bin下. 3 Common 通用类加载器 加载tomcat使用以及应用通用的一些类,位于CATALIN

Tomcat类加载机制

说到本篇的tomcat类加载机制,不得不说翻译学习tomcat的初衷. 之前实习的时候学习javaMelody的源码,但是它是一个Maven的项目,与我们自己的web项目整合后无法直接断点调试.后来同事指导,说是直接把java类复制到src下就可以了.很纳闷....为什么会优先加载src下的java文件(编译出的class),而不是jar包中的class呢? 现在了解tomcat的类加载机制,原来一切是这么的简单. 类加载 在JVM中并不是一次性把所有的文件都加载到,而是一步一步的,按照需要来加

Java和Tomcat类加载机制

加载类是运行程序的基础,了解Java和Tomcat的类加载机制对更有效地开发.调试Web应用程序有一定的积极作用.本文简单介绍Java和Tomcat的类加载机制,希望对大家有所帮助. •JDK/JRE文件结构 在安装JDK后,其典型的目录层次如下所示(JDK 1.6.0): 主要的目录和JAR简述如下: •<JAVA_HOME>\bin: 包含在JDK中的开发工具的可执行文件,一般而言,PATH环境变量应包含该目录. •<JAVA_HOME>\lib: 开发工具使用的文件,其中包括

图解Tomcat类加载机制

说到本篇的tomcat类加载机制,不得不说翻译学习tomcat的初衷. 之前实习的时候学习javaMelody的源码,但是它是一个Maven的项目,与我们自己的web项目整合后无法直接断点调试.后来同事指导,说是直接把java类复制到src下就可以了.很纳闷....为什么会优先加载src下的java文件(编译出的class),而不是jar包中的class呢? 现在了解tomcat的类加载机制,原来一切是这么的简单. 类加载 在JVM中并不是一次性把所有的文件都加载到,而是一步一步的,按照需要来加

图解JVM和Tomcat类加载机制

说到本篇的tomcat类加载机制,不得不说翻译学习tomcat的初衷. 之前实习的时候学习javaMelody的源码,但是它是一个Maven的项目,与我们自己的web项目整合后无法直接断点调试.后来同事指导,说是直接把java类复制到src下就可以了.很纳闷....为什么会优先加载src下的java文件(编译出的class),而不是jar包中的class呢? 现在了解tomcat的类加载机制,原来一切是这么的简单. 类加载 在JVM中并不是一次性把所有的文件都加载到,而是一步一步的,按照需要来加

《转载》图解Tomcat类加载机制

本文转载自http://www.cnblogs.com/xing901022/p/4574961.html 说到本篇的tomcat类加载机制,不得不说翻译学习tomcat的初衷. 之前实习的时候学习javaMelody的源码,但是它是一个Maven的项目,与我们自己的web项目整合后无法直接断点调试.后来同事指导,说是直接把java类复制到src下就可以了.很纳闷....为什么会优先加载src下的java文件(编译出的class),而不是jar包中的class呢? 现在了解tomcat的类加载机

Tomcat、Websphere和Jboss类加载机制

http://blog.csdn.net/lshxy320/article/details/6448972 2       Tomcat 类加载机制 Tomcat Server 在启动的时候将构造一个 ClassLoader 树,以保证模块的类库是私有的     Tomcat Server 的 ClassLoader 结构图如下: - Bootstrap - 载入 JVM 自带的类和 /jre/lib/ext/*.jar - System - 载入 /*.class - Common - 载入 

虚拟机类加载机制(3)——线程上下文类加载器

之所以将线程上下文类加载器(Thread Context ClassLoader)单独拿出来写,确实是因为它涉及的东西比较多,既然带有线程两个字,一定也是非常重要的一个东西. 我们首先来回顾一下类加载器的双亲委派模型. 在上一章<虚拟机类加载机制(2)——类加载器>中我们解释了何为类加载器的“双亲委派模型”,知道了双亲委派模型给我们带了一个好处就是Java类随着它的类一起具备了一种带有优先级的层次关系.简单的例子就是Object类在程序的各种类加载环境中都会由启动类加载器来加载,换言之,它无论