24 | Context容器(上):Tomcat如何打破双亲委托机制?
该思维导图由 AI 生成,仅供参考
JVM 的类加载器
- 深入了解
- 翻译
- 解释
- 总结
Tomcat的类加载器是如何打破双亲委托机制的?本文深入解析了JVM的类加载机制和Tomcat的自定义类加载器WebAppClassLoader的实现原理。首先介绍了JVM的类加载机制,包括ClassLoader的层次结构和关键方法,以及JDK中默认的类加载器。重点解释了双亲委托机制的作用,即保证JVM中的类是唯一的。文章指出,要打破双亲委托机制,需要重写loadClass方法,因为loadClass的默认实现就是双亲委托机制。然后详细分析了Tomcat的类加载器的findClass和loadClass方法的实现,展示了Tomcat是如何通过自定义类加载器来实现自己的类加载逻辑,优先加载Web应用自己定义的类。通过对Tomcat类加载器的源码剖析,读者可以深入了解Java类加载机制的实现原理,以及如何打破双亲委托机制。文章内容丰富,对于想深入了解JVM类加载机制和Tomcat类加载器实现的读者具有很高的参考价值。
《深入拆解 Tomcat & Jetty 》,新⼈⾸单¥68
全部留言(58)
- 最新
- 精选
- 罗 乾 林我想打破双亲委托机制,能保证不同版本的类共存,就像一个tomcat下多个工程,使用了不同版本的spring,各加载各的互不影响。如果不打破双亲委托机制,都交由AppClassLoader去加载,那么相同包名相同类名的类就被判定已经加载过了,达不到加载不同版本的功能。由于自定义了类加载器,即使包名与类名相同,但类加载器不同依然被判断为不同的类
作者回复: 对的,下一篇就说隔离
2019-07-0643 - nightmaretomcat的类加载机制老师剖析的很透彻,先扩展类加载器加载,这样避免自己覆盖JRE中的类然后再自定义的加载器加载,最后应用加载器加载,有一个疑问,就是比如我一个tomcat部署了多个web应用,如果都有spring的jar包,由于自定义的类加载器先加载spring的jar包,这样spring的jar在每一个context应用岂不是都要加载一次?如果应用加载器先加载,是不是就可以只加载一次spring的jar,然后自定义的加载器只加载不共用的class?
作者回复: 你说的很对,Spring的类应该是由sharedclassloader来加载,所以不应该把Spring的包放到Web应用的路径下,应该放到Tomcat指定的共享目录下
2019-07-0431 - Monday1、原文【tomcat 的自定义类加载器 WebAppClassLoader 打破了双亲委托机制,它首先自己尝试去加载某个类,如果找不到再代理给父类加载器,其目的是优先加载 Web 应用自己定义的类。具体实现就是重写 ClassLoader 的两个方法:findClass 和 loadClass。】 问题:就不怕tomcat类加载器覆盖ExtClassloader加载的类? 2、原文【从上面的过程我们可以看到,Tomcat 的类加载器打破了双亲委托机制,没有一上来就直接委托给父加载器,而是先在本地目录下加载,为了避免本地目录下的类覆盖 JRE 的核心类,先尝试用 JVM 扩展类加载器 ExtClassLoader 去加载。那为什么不先用系统类加载器 AppClassLoader 去加载?很显然,如果是这样的话,那就变成双亲委托机制了,这就是 Tomcat 类加载器的巧妙之处。】 问题:后面的回答,感觉像是为了打破而打破似的。 3、听/看本节多次,最后还是没体悟到Tomcat打破双亲委托模式的好处。。。
作者回复: 假如web应用目录下有个Spring2.0版本的库,系统class类路径下有个Spring 1.0版本的库,打破双亲委托的好处是web应用会加载web应用路径下那个Spring。
2019-07-08522 - 吖蒲老师,我看源码了还是有点不懂,第三步骤tomcat的类加载器先用extclassloader加载类,ext让父加载器bootstrap去加载,防止优先加载应用中同名的类,那我用appclassloader,最终也能达到bootstrap加载器去加载类的效果,那为什么不直接调用appclassloader加载??
作者回复: 好问题,appclassloader会加载PATH目录下的类,这样就达不到优先加载web应用目录下类的目的了
2019-08-08416 - nightmare我明白了,比如可以把多个项目共享的jar包放到${CATALINA_HOME}/shared目录下,让sharedclassloader来加载,并且是所有context的web应用共享的,而都有的放在web路径下,先让扩展类加载器加载,避免覆盖jre中的类,再让自定义的web加载器来加载独有的类,最后加载让应用加载器加载扩展类加载器和自定义加载器加载不到的类,谢谢李老师
作者回复: 👍
2019-07-04215 - 强哥每篇文章最后的总结,若能概括出这么做的意图及优点,这样对读者来说收益更大。
作者回复: Servlet规范建议,全路径类名与系统类同名的话,优先加载web应用自己定义的类。
2019-07-0413 - Li Shunduo在其他地方看到过可以通过配置<Loader delegate="true"/>让tomcat遵循双亲委派,老师在答疑篇可以展开讲讲吗?
作者回复: 是的,如果你不想Tomcat打破双亲委托,可以配这个参数
2019-07-1011 - Mr.差不多双亲委派规则是 当父加载器找不到此文件时才交给子加载器去加载。那么我觉得Tomcat重写loadClass方法其实也是这个逻辑。假设现在有一个类是需要在WebAppClassLoader加载的,那么它会先查询是否在AppClassLoader加载过,如果没有那么查看是否在ExtClassLoader加载过,那么这一系列步骤不就是为了保证没有在父加载器找不到此文件吗?这不还是双亲委派的模型吗?麻烦老师给解答下
作者回复: WebAppClassLoader不会首先委托给AppClassLoader去加载,而是ExtClassLoader。这是根本区别
2019-07-05311 - Liam老师能讲下什么是上下文加载器吗,什么情况下会用到它?这个和双亲委派有关吗
作者回复: 线程上下文加载器其实是线程私有数据,跟线程绑定的属性
2019-07-0439 - 飞翔老师 您说 java 的类加载器,就是把字节码格式.class 文件加载到JVM的方法区,并在JVM的堆区建立一个java.lang.Class 对象实例 那loadclass方法负责把字节码格式.class 文件加载到JVM的方法区 和defineclass负责在JVM的堆区建立一个java.lang.Class 对象实例 这样理解对嘛
作者回复: 对的
2019-07-238