Tomcat类加载机制

梦里梦外; 2022-09-12 03:51 375阅读 0赞
  • 一:双亲委派模型

双亲委派模型要求除了顶层的启动类加载器之外,其余的类加载器都应当由自己的父类加载器加载。

3859a4d3c80a51c151a92aa3f1f011e6.png

Tomcat的类加载机制是违反了双亲委托原则的,对于一些未加载的非基础类(Object,String等),各个web应用自己的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给commonClassLoader走双亲委托。

二:Tomcat的加载机制

  • 结论先行:

    • 对于一些标准类库中的类,比如Object类,会让系统类加载器加载,然后一直委托到启动类加载器,这个过程是没有违背双亲委派的
    • 对于一些非基础类库则是webappClassLoader自行去加载,加载失败才让父加载器加载,明显是违背双亲委派的。
    • tomcat也不是完全违反了双亲委派机制,从整体角度来看是违反了双亲委派机制,但核心的Java类库的加载还是遵从双亲委派 。在Tomcat中,默认的行为是先尝试在Bootstrap和Extension中进行类型加载,如果加载不到则在WebappClassLoader中进行加载,如果还是找不到则在Common中进行查找 ,如下图:

      • 1、在系统目录中加载标准类库中的类,使用的是Bootstrap ClassLoad ,Extension ClassLoad
      • 2、使用WebApp ClassLoad加载类库
      • 3、WebappClassLoader找不到则委托给父类加载器Common ClassLoad去加载
  • 图解:

  • 在这里插入图片描述

  • watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 1

  • tomcat类加载过程

    • tomcat的类加载机制是违反了双亲委托原则的,对于一些未加载的非基础类(Object,String等),各个web应用自己的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给commonClassLoader走双亲委托。具体的加载逻辑位于WebAppClassLoaderBase.loadClass()方法中,代码篇幅长,这里以文字描述加载一个类过程:

      1. resourceEntries这个数据结构中),如果已经加载即返回,否则 继续下一步。
      2. 让系统类加载器(AppClassLoader)尝试加载该类,主要是为了防止一些基础类会被web中的类覆盖,如果加载到即返回,返回继续。
      3. 前两步均没加载到目标类,那么web应用的类加载器将自行加载,如果加载到则返回,否则继续下一步。
      4. 最后还是加载不到的话,则委托父类加载器(Common ClassLoader)去加载。
      5. 第3第4两个步骤的顺序已经违反了双亲委托机制,除了tomcat之外,JDBC,JNDI,Thread.currentThread().setContextClassLoader();等很多地方都一样是违反了双亲委托。
  • tomcat架构解析(刘光瑞)引用:

    1. ![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBAUGFzc2VyQnkqXyo_size_20_color_FFFFFF_t_70_g_se_x_16][]
  1. ![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBAUGFzc2VyQnkqXyo_size_20_color_FFFFFF_t_70_g_se_x_16 1][]

三:Tomcat是个web容器, 它要解决什么问题?

  1. 一个web容器可能需要部署两个应用程序,不同的应用程序可能会依赖同一个第三方类库的不同版本,不能要求同一个类库在同一个服务器只有一份,因此要保证每个应用程序的类库都是独立的,保证相互隔离。
  2. 部署在同一个web容器中相同的类库相同的版本可以共享。否则,如果服务器有10个应用程序,那么要有10份相同的类库加载进虚拟机,这是扯淡的。
  3. web容器也有自己依赖的类库,不能与应用程序的类库混淆。基于安全考虑,应该让容器的类库和程序的类库隔离开来。
  4. web容器要支持jsp的修改,我们知道,jsp 文件最终也是要编译成class文件才能在虚拟机中运行,但程序运行后修改jsp已经是司空见惯的事情,否则要你何用? 所以,web容器需要支持 jsp 修改后不用重启。

四:Tomcat 如果使用默认的类加载机制行不行?

  • 答案是不行的。
  • 默认的类加载器是能够实现的,因为他的职责就是保证唯一性,而我们tomcat有时候需要加载两个相同类库的不同版本,而默认的类加载器是不管你是什么版本的,只在乎你的全限定类名,并且只有一份。

五:问题

  1. 既然 Tomcat 不遵循双亲委派机制,那么如果我自己定义一个恶意的HashMap,会不会有风险呢?(阿里的面试官问)

    • 答1: 显然不会有风险,如果有,Tomcat都运行这么多年了,那群Tomcat大神能不改进吗? tomcat不遵循双亲委派机制,只是自定义的classLoader顺序不同,但顶层还是相同的,
    • 答2:Tomcat也不是完全违反了双亲委派机制,从整体角度来看是违反了双亲委派机制,但核心的Java类库的加载还是遵从双亲委派 。在Tomcat中,默认的行为是先尝试在Bootstrap和Extension中进行类型加载,如果加载不到则在WebappClassLoader中进行加载,如果还是找不到则在Common中进行查找 流程如上(二:Tomcat的加载机制)图

参考:

Tomcat - 都说Tomcat违背了双亲委派机制,到底对不对?_小工匠-CSDN博客

图解Tomcat类加载机制(阿里面试题)_xiaobao5214的博客-CSDN博客

深度思考:老生常谈的双亲委派机制,JDBC、Tomcat是怎么反其道而行之的?

#

发表评论

表情:
评论列表 (有 0 条评论,375人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Tomcat机制

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

    相关 Tomcat机制

    一:双亲委派模型 双亲委派模型要求除了顶层的启动类加载器之外,其余的类加载器都应当由自己的父类加载器加载。 ![3859a4d3c80a51c151a92aa3f

    相关 图解Tomcat机制

           之前学习javaMelody的源码,但是它是一个Maven的项目,与我们自己的web项目整合后无法直接断点调试。后来同事指导,说是直接把java类复制到src下就