Tomcat 的类加载机制

article/2025/9/19 9:25:27

        在前面 Java虚拟机:对象创建过程与类加载机制、双亲委派模型 文章中,我们介绍了 JVM 的类加载机制以及双亲委派模型,双亲委派模型的类加载过程主要分为以下几个步骤:

  • (1)初始化 ClassLoader 时需要指定自己的 parent 是谁
  • (2)先检查类是否已经被加载过,如果类已经被加载了,直接返回
  • (3)若没有加载则调用父加载器 parent 的 loadClass() 方法进行加载
  • (4)若父加载器为空则默认使用启动类加载器 bootstrap ClassLoader 进行加载
  • (5)如果父类加载失败,抛出 ClassNotFoundException 异常后,再调用自己的 findClass() 方法进行加载。

        前面文章也提到,如果想要破坏这种机制,那么就自定义一个类加载器(继承自 ClassLoader),并重写其中的 loadClass() 方法,使其不进行双亲委派即可。最经典例子就是 Tomcat 容器的类加载机制了,它实现了自己的类加载器 WebApp ClassLoader,并且打破了双亲委派模型,在每个应用在部署后,都会创建一个唯一的类加载器。

1、Tomcat 的类加载器结构图:

(1)Common ClassLoader:加载 common.loader 属性下的 jar,一般是 CATALINA_HOME/lib 目录下,主要是 tomcat 使用以及应用通用的一些类

(2)Catalina ClassLoader:加载 server.loader 属性下的 jar,默认未配置路径,返回其父加载器即 Common ClassLoader,主要是加载服务器内部可⻅类,这些类应⽤程序不能访问;

(3)Shared Classloader:加载 share.loader 属性下的jar,默认未配置路径,返回其父加载器即 Common ClassLoader,主要是加载应⽤程序共享类,这些类对 Tomcat 自己不可见;

只有指定了 tomcat/conf/catalina.properties 配置文件的 server.loader 和 share.loader 项后,才会真正建立 Catalina ClassLoader 和 Shared ClassLoader 的实例,否则在用到这两个类加载器的地方都会用 Common ClassLoader 的实例代替,而默认的配置文件中是没有设置这两个 loader 项的

(4)WebApp ClassLoader:Tomcat 可以存在多个 WebApp ClassLoader 实例,每个应⽤程序都会有⼀个独⼀⽆⼆的 WebApp ClassLoader,⽤来加载本应⽤程序 /WEB-INF/classes 和 /WEB-INF/lib 下的类。

2、Tomcat 的类加载流程说明:

当 Tomcat 使用 WebAppClassLoader 进行类加载时,具体过程如下:

(1)先在本地 cache 缓存中查找该类是否已经加载过,看看 Tomcat 有没有加载过这个类

(2)如果 Tomcat 没有加载过这个类,则从系统类加载器的 cache 缓存中查找是否加载过

(3)如果没有,则使用 ExtClassLoader 类加载器类加载,重点来了,Tomcat 的 WebAppClassLoader 并没有先使用 AppClassLoader 来加载类,而是直接使用了 ExtClassLoader 来加载类。不过 ExtClassLoader 依然遵循双亲委派,它会使用 Bootstrap ClassLoader 来对类进行加载,保证了 Jre 里面的核心类不会被重复加载。

比如在 Web 中加载一个 Object 类。WebAppClassLoader → ExtClassLoader → Bootstrap ClassLoader,这个加载链,就保证了 Object 不会被重复加载。

(4)如果没有加载成功,WebAppClassLoader 就会调用自己的 findClass() 方法由自己来对类进行加载,先在 WEB-INF/classes 中加载,再从 WEB-INF/lib 中加载。

(5)如果仍然未加载成功,WebAppclassLoader 会委派给 SharedClassLoader,SharedClassLoad 再委派给 CommonClassLoader,CommonClassLoader 委派给 AppClassLoader,直到最终委派给 BootstrapClassLoader,最后再一层一层地在自己目录下对类进行加载。

(6)都没有加载成功的话,抛出异常。

3、源码解析:

(1)WebAppClassLoader 的 loadClass() 方法源码:

WebappClassLoader 应用类加载器的 loadClass 在他的父类 WebappClassLoaderBase 中

public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {synchronized (getClassLoadingLock(name)) {Class<?> clazz = null;//1. 先在本地cache查找该类是否已经加载过clazz = findLoadedClass0(name);if (clazz != null) {if (resolve)resolveClass(clazz);return clazz;}//2. 从系统类加载器的cache中查找是否加载过clazz = findLoadedClass(name);if (clazz != null) {if (resolve)resolveClass(clazz);return clazz;}// 3. 尝试用ExtClassLoader类加载器类加载(ExtClassLoader 遵守双亲委派,ExtClassLoader 会使用 Bootstrap ClassLoader 对类进行加载)ClassLoader javaseLoader = getJavaseClassLoader();try {clazz = javaseLoader.loadClass(name);if (clazz != null) {if (resolve)resolveClass(clazz);return clazz;}} catch (ClassNotFoundException e) {// Ignore}// 4. 尝试在本地目录搜索class并加载try {clazz = findClass(name);if (clazz != null) {if (resolve)resolveClass(clazz);return clazz;}} catch (ClassNotFoundException e) {// Ignore}// 5. 尝试用系统类加载器(AppClassLoader)来加载try {clazz = Class.forName(name, false, parent);if (clazz != null) {if (resolve)resolveClass(clazz);return clazz;}} catch (ClassNotFoundException e) {// Ignore}}//6. 上述过程都加载失败,抛出异常throw new ClassNotFoundException(name);
}

(2)WebAppClassLoader 的 findClass() 方法源码:

public Class<?> findClass(String name) throws ClassNotFoundException {// Ask our superclass to locate this class, if possible// (throws ClassNotFoundException if it is not found)Class<?> clazz = null;// 先在自己的 Web 应用目录下查找 classclazz = findClassInternal(name);// 找不到 在交由父类来处理if ((clazz == null) && hasExternalRepositories) {  clazz = super.findClass(name);}if (clazz == null) {throw new ClassNotFoundException(name);}return clazz;
}

4、为什么tomcat要实现自己的类加载机制:

        WebAppClassLoader 加载类的时候,故意打破了JVM 双亲委派机制,绕开了 AppClassLoader,直接先使用 ExtClassLoader 来加载类。最主要原因是保证部署在同一个 Web 容器上的不同 Web 应用程序所使用的类库可以实现相互隔离,避免不同项目的相互影响。当然还有其他原因,如:

(1)保证 Web 容器自身的安全不受部署的 Web 应用程序影响,所以 Tomcat 使用的类库要与部署的应用的类库相互独立

(2)保证部分基础类不会被同时加载,有些类库 Tomcat 与部署的应用可以共享,比如说 servlet-api

(3)保证部署在同一个 Web 容器的应用之间的类库可以共享,这听起来好像主要原因相互矛盾,但其实这很合理,类被类加载器加载到虚拟机后,会存放在方法区的永久代中,如果类库不能共享,虚拟机的方法区就会很容易出现过度膨胀的风险。比如这时候如果有大量的应用使用 spring 来管理,如果 spring 类库不能共享,那每个应用的 spring 类库都会被加载一次,将会是很大的资源浪费。

小结:Tomcat 实际上只有 WebAppClassLoader 加载器中打破了双亲委派,其他类加载器还是遵循双亲委派的。 这样做最主要原因是保证同个 Web 容器中的不同 Web 应用程序所使用的类库相互独立,避免相互影响

参考文章:https://mp.weixin.qq.com/s/OwWUDxHY4Th6decmJeMTgA


http://chatgpt.dhexx.cn/article/0QmNvJga.shtml

相关文章

java类加载机制

最近开通了一个订阅号 gexiaolong 在其中记录一些关于java总是记了又忘&#xff0c;忘了又记的一些知识点&#xff0c;所以还是写一篇日志记录一下吧 老规矩&#xff0c;抄作业&#xff0c;关于java的类加载机制的问题也是看了忘&#xff0c;忘了又在看 在此梳理记录一下 说…

类加载机制详解

一、类加载机制 Java虚拟机把描述类的数据从Class文件加载进内存&#xff0c;并对数据进行校验&#xff0c;转换解析和初始化&#xff0c;最终形成可以被虚拟机直接使用的Java类型&#xff0c;这就是虚拟机的类加载机制。 虚拟机设计团队把类加载阶段中的“通过一个类的全限定…

类的加载机制

文章目录 前言类加载的生命周期&#xff1a;加载&#xff08;Loading&#xff09;、验证&#xff08;Verification&#xff09;、准备&#xff08;PreParation&#xff09;、解析(Resolution)、初始化、使用、销毁&#xff0c;其中验证&#xff0c;准备&#xff0c;解析又叫做连…

类加载机制

1、JVM 和 类 &#xff08;1&#xff09;运行java命令&#xff1a; java 带有main方法的类名 ■ 命令的作用&#xff1a;启动jvm&#xff0c;并加载字节码&#xff0c;执行程序 当调用java命令来运行某个java程序时&#xff0c;该命令将会启动一个jvm进程&#xff08;同一个…

双亲委派模型的破坏

一、类加载机制 Java虚拟机把描述类的数据从Class文件加载进内存&#xff0c;并对数据进行校验&#xff0c;转换解析和初始化&#xff0c;最终形成可以被虚拟机直接使用的Java类型&#xff0c;这就是虚拟机的类加载机制。 虚拟机设计团队把类加载阶段中的“通过一个类的全限定…

类加载机制(整个过程详解)

一:背景 类加载机制是在我们的真个java的运行阶段中的其中一个阶段。 二:什么是快乐星球(类加载机制) 我们编写的 Java 文件都是以.java 为后缀的文件&#xff0c;编译器会将我们编写的.java 的文件编译成.class 文件&#xff0c;简单来说类加载机制就是jvm从文件系统将一系…

TCP/IP四层模型---应用层

相对于OSI七层模型,TCP/IP四层模型更为简化,总结为应用层,传输层,网络层,数据链路层四层 简单来说,四层协议分别为: 协议 应用层DNS,URI,HTML,HTTP,SSL,SMTP,POP,IMAPTELNET,SSH,FTP,SNMP应用程序相关传输层TCP,UDP,UDP-Lite,SCTP,DCCP操作系统内核负责网络层ARP,IP,ICMP数据链…

OSI七层网络模型与TCP/IP四层网络模型

OSI模型&#xff0c;即开放式通信系统互联参考模型(Open System Interconnection,OSI/RM,Open Systems Interconnection Reference Model)&#xff0c;是国际标准化组织(ISO)提出的一个试图使各种计算机在世界范围内互连为网络的标准框架&#xff0c;简称OSI。 OSI网络模型按照…

TCP/IP五层(四层)模型

TCP/IP五层&#xff08;四层&#xff09;模型中包含的协议有很多&#xff0c;其中典型代表是TCP协议和IP协议。 应用层&#xff1a;应用程序直接打交道的协议。在实际开发中涉及最多的部分&#xff0c;甚至需要自己设计应用层协议。 传输层&#xff1a;负责端到端之间的传输。&…

【计算机网络】TCP/IP四层模型和OSI七层模型

文章目录 一、TCP/IP四层模型和OSI七层模型关系二、TCP/IP四层模型三、OSI七层模型四、GET和POST的区别五、从输入网址到页面展示的过程六、详细过程 一、TCP/IP四层模型和OSI七层模型关系 1、OSI引进了服务、接口、协议、分层的概念&#xff0c;TCP/IP借鉴了OSI的这些概念建立…

TCP/IP四层模型与OSI七层模型

1&#xff09;网络协议 【网络协议】是【网络上所有设备】&#xff08;网络服务器、计算机及交换机、路由器、防火墙等&#xff09;之间【通信规则】的【集合】&#xff0c;它规定了进行【网络中的对等实体数据交换】而建立的规则。由于大多数网络采用【分层的体系结构】&…

OSI七层模型和TCPIP四层网络模型

OSI七层模型和TCP/IP四层网络模型 写在文前&#xff0c;本篇文章是在学习过程抄录的笔记&#xff0c;需要更详细的内容可以在微信搜索javaguide公众号获取。1、OSI划分 七层划分&#xff1a;应用层、表示层、会话层、传输层、网络层、数据链路层、物理层五层划分&#xff1a;…

读懂TCP IP四层模型与OSI七层模型

目录 一、OSI七层模型 二、TCP/IP四层模型 三、OSI模型的七层解读 3.1 OSI七层模型小结 3.2 TCP/IP模型与OSI模型的对应关系 四、常见的网络相关协议 五、TCP和UDP协议 5.1 TCP三次握手 5.2 TCP四次挥手 5.3 UDP协议 5.4 TCP和UDP的区别 六、TCP/IP四层模型与OSI七…

Linux网络_从系统到网络(网络协议栈分层与功能,认识协议,OSI七层模型与TCPIP四层模型,网络通信流程(局域网,跨网络),MAC地址,IP地址)

文章目录 1.网络在体系结构的位置与网络协议栈的层状结构2.协议栈各层的功能3.协议4.OSI七层模型与TcpIp四层模型5.网络通信的流程局域网通信流程(以太网)MAC地址跨网络通信IP地址 1.网络在体系结构的位置与网络协议栈的层状结构 2.协议栈各层的功能 协议栈分层设计达到了解耦目…

TCP/IP五层(或四层)模型

图解TCP/IP协议 基本概念 1、TCP连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议&#xff0c;可以使手机终端通过无线网络建立TCP连接。TCP协议可以对上层网络提供接口&#xff0c;使上层网络数据的传输建立在“无差别”的网络之上。 建立起一个TCP连接需要经过“三…

matlab怎么画两个自变量的图_tcpip四层模型怎么画?画模型图的好用软件推荐

tcpip四层模型就是一个将osi参考模型的会话层和表示层合并到应用层&#xff0c;数据链路层和物理层合并为链路层后的结果。tcpip四层模型包含应用层、运输层、网络层和链路层。tcpip四层模型的协议功能包括数据的发送、与硬件的交互、消息路由规则、格式定义、错误验证。 tcpip…

TCP/IP四层模型与OSI七层参考模型(网络协议)

TCP/IP四层模型与OSI七层参考模型 一. OSI七层参考模型①. 物理层②. 数据链路层③. 网络层④. 传输层⑤. 会话层⑥. 表示层⑦. 应用层 二. TCP/IP模型①. 物理层②. 数据链路层---网络协议③. 网络层---网络协议④. 传输层---网络协议⑤. 应用层---网络协议 三 .TCP/IP四层模型…

网络分层(OSI7层模型和TCP/IP四层模型)

1 OSI七层模型 1.1 物理层 主要定义物理设备标准&#xff0c;如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流&#xff08;就是由1、0转化为电流强弱来进行传输&#xff0c;到达目的地后再转化为1、0&#xff0c;也就是我们常说的数模…

TCPIP四层模型和OSI七层模型对应表

转载于:https://www.cnblogs.com/Pual623548198/p/7084421.html