深入源代码,探秘Tomcat类加载机制:为何颠覆双亲委派原则(1)?

1.什么是双亲委派

  jvm启动后会通过其类装载子系统,去硬盘上找xxx.class文件,找到之后,会直接将xxx这个类装载到java虚拟机中,这个过程叫做类的加载。而类的加载过程中就涉及到了双亲委派。

  类加载机制的双亲委派(Parent Delegation Model)是Java中的一种类加载策略,旨在确保Java应用程序的安全性和一致性。其基本原理如下:

  1. 加载顺序:当一个类加载器接到加载某个类的请求时,它首先会将该请求委派给它的父类加载器。如果父类加载器能够加载这个类,则请求返回给调用者;如果父类加载器无法加载该类,加载请求才会被当前类加载器处理。

  2. 层级结构:Java的类加载器通常以树形结构组织,顶层是引导类加载器(Bootstrap ClassLoader),接下来是扩展类加载器(Extension ClassLoader)和应用类加载器(Application ClassLoader)。每个加载器都有自己的父加载器。

  3. 避免重复加载:通过这种机制,Java避免了同一个类被多个类加载器加载的情况,从而防止类的冲突和版本不一致的问题。例如,如果系统中有两个不同版本的同一类,双亲委派机制确保只有一个版本会被加载,避免了潜在的错误和不兼容。

  4. 安全性:双亲委派机制也增强了Java的安全性,因为它优先加载Java核心类库中的类,而不是用户自定义的类。这意味着用户无法轻易地替换系统核心的类,防止了潜在的安全漏洞。

  双亲委派整体流程如下图:

2.Tomcat为什么需要打破双亲委派呢

  首先需要明确,在jvm中一个class对象是否唯一,主要依赖于类加载器和类的全限定名,如果二者均一样,那么说明两个class对象一样。

  那么问题来了,tomcat是一个servlet容器,再该容器下我们可以部署多个项目,如果仅依赖于全局的类加载机制(双亲委派机制),那么如果我们在该容器下部署了两个项目,项目中均存在一个全限定名为com.controller.HelloWord的类,但是该类的方法和属性完全不同。如果按照双亲委派机制使用全局的Application ClassLoader来加载该类,那么该类因为类加载器和全限定名一致,所以只会被加载一次,这样就会存在问题。所以Tomcat通过自定义加载器的方式打破了双亲委派机制。

  注意:所谓的打破并不是完全不遵守双亲委派机制,Tomcat通过为每个context(项目)定义自己的WebAppClassLoader,加载项目内的class对象,对于一些公共的,比如jdk提供的数据类型等还是要走双亲委派机制。

3.Tomcat的类加载机制

  Tomcat的启动加载跟普通项目一样,因为其本身就是一个Java项目,有自己的main方法启动类,但是Tomcat在jvm的基础上自定义了很多类加载器,其整体工作流程如下:

   上面的橙色部门还是和原来一样, 采用双亲委派机制。 而黄色部分是Tomcat第一部分自定义的类加载器,这部分主要是加载Tomcat包中的类,这一部分依然采用的是双亲委派机制,而绿色部分是Tomcat第二部分自定义类加载器,正是这一部分,打破了类的双亲委派机制。下面我们就来详细看看Tomcat自定的类加载器:

  • commonClassLoader: tomcat最基本的类加载器, 加载路径中的class可以被tomcat容器本身和各个webapp访问,如Servlet规范相关包和一些通用工具包;

  • catalinaClassLoader: tomcat容器中私有的类加载器, 加载路径中的class对于webapp不可见。

  • sharedClassLoader: 各个webapps共享的类加载器, 加载路径中的class对于所有的webapp都可见, 但是对于tomcat容器不可见。

  • WebappClassLoader:各个Webapp私有的类加载器,加载路径中的class只对当前Webapp可见;每一个应用会创建一个该对象实例进行加载  其加载目录为每个应用的WEB-INF/class以及lib。

  注意:再高版本的Tomcat中,黄色部分进行了合并(默认情况下三个加载器使用了同一个,但是通过配置仍可以恢复成三个不一样的类加载器),合并后的工作流程如下:

4.从源码层面探究Tomcat的类加载机制

    Tomcat也是一个Java项目,其启动时也是执行Bootstrap中的main方法,如下图:

  接下来我们就详细的看一下initClassLoaders(),是如何初始化类加载器以及他们的关系:

深入源代码,探秘Tomcat类加载机制:为何颠覆双亲委派原则(2)?-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值