Tomcat类加载机制
双亲委派模型要求除了顶层的启动类加载器之外,其余的类加载器都应当由自己的父类加载器加载。
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去加载
图解:
tomcat类加载过程
tomcat的类加载机制是违反了双亲委托原则的,对于一些未加载的非基础类(Object,String等),各个web应用自己的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给commonClassLoader走双亲委托。具体的加载逻辑位于WebAppClassLoaderBase.loadClass()方法中,代码篇幅长,这里以文字描述加载一个类过程:
- resourceEntries这个数据结构中),如果已经加载即返回,否则 继续下一步。
- 让系统类加载器(AppClassLoader)尝试加载该类,主要是为了防止一些基础类会被web中的类覆盖,如果加载到即返回,返回继续。
- 前两步均没加载到目标类,那么web应用的类加载器将自行加载,如果加载到则返回,否则继续下一步。
- 最后还是加载不到的话,则委托父类加载器(Common ClassLoader)去加载。
- 第3第4两个步骤的顺序已经违反了双亲委托机制,除了tomcat之外,JDBC,JNDI,Thread.currentThread().setContextClassLoader();等很多地方都一样是违反了双亲委托。
tomcat架构解析(刘光瑞)引用:
![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBAUGFzc2VyQnkqXyo_size_20_color_FFFFFF_t_70_g_se_x_16][]
![watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBAUGFzc2VyQnkqXyo_size_20_color_FFFFFF_t_70_g_se_x_16 1][]
三:Tomcat是个web容器, 它要解决什么问题?
- 一个web容器可能需要部署两个应用程序,不同的应用程序可能会依赖同一个第三方类库的不同版本,不能要求同一个类库在同一个服务器只有一份,因此要保证每个应用程序的类库都是独立的,保证相互隔离。
- 部署在同一个web容器中相同的类库相同的版本可以共享。否则,如果服务器有10个应用程序,那么要有10份相同的类库加载进虚拟机,这是扯淡的。
- web容器也有自己依赖的类库,不能与应用程序的类库混淆。基于安全考虑,应该让容器的类库和程序的类库隔离开来。
- web容器要支持jsp的修改,我们知道,jsp 文件最终也是要编译成class文件才能在虚拟机中运行,但程序运行后修改jsp已经是司空见惯的事情,否则要你何用? 所以,web容器需要支持 jsp 修改后不用重启。
四:Tomcat 如果使用默认的类加载机制行不行?
- 答案是不行的。
- 默认的类加载器是能够实现的,因为他的职责就是保证唯一性,而我们tomcat有时候需要加载两个相同类库的不同版本,而默认的类加载器是不管你是什么版本的,只在乎你的全限定类名,并且只有一份。
五:问题
既然 Tomcat 不遵循双亲委派机制,那么如果我自己定义一个恶意的HashMap,会不会有风险呢?(阿里的面试官问)
- 答1: 显然不会有风险,如果有,Tomcat都运行这么多年了,那群Tomcat大神能不改进吗? tomcat不遵循双亲委派机制,只是自定义的classLoader顺序不同,但顶层还是相同的,
- 答2:Tomcat也不是完全违反了双亲委派机制,从整体角度来看是违反了双亲委派机制,但核心的Java类库的加载还是遵从双亲委派 。在Tomcat中,默认的行为是先尝试在Bootstrap和Extension中进行类型加载,如果加载不到则在WebappClassLoader中进行加载,如果还是找不到则在Common中进行查找 流程如上(二:Tomcat的加载机制)图
参考:
Tomcat - 都说Tomcat违背了双亲委派机制,到底对不对?_小工匠-CSDN博客
图解Tomcat类加载机制(阿里面试题)_xiaobao5214的博客-CSDN博客
深度思考:老生常谈的双亲委派机制,JDBC、Tomcat是怎么反其道而行之的?
还没有评论,来说两句吧...