• 罗乾林
    2019-07-06
    我想打破双亲委托机制,能保证不同版本的类共存,就像一个tomcat下多个工程,使用了不同版本的spring,各加载各的互不影响。如果不打破双亲委托机制,都交由AppClassLoader去加载,那么相同包名相同类名的类就被判定已经加载过了,达不到加载不同版本的功能。由于自定义了类加载器,即使包名与类名相同,但类加载器不同依然被判断为不同的类

    作者回复: 对的,下一篇就说隔离

    
     12
  • nightmare
    2019-07-04
    tomcat的类加载机制老师剖析的很透彻,先扩展类加载器加载,这样避免自己覆盖JRE中的类然后再自定义的加载器加载,最后应用加载器加载,有一个疑问,就是比如我一个tomcat部署了多个web应用,如果都有spring的jar包,由于自定义的类加载器先加载spring的jar包,这样spring的jar在每一个context应用岂不是都要加载一次?如果应用加载器先加载,是不是就可以只加载一次spring的jar,然后自定义的加载器只加载不共用的class?

    作者回复: 你说的很对,Spring的类应该是由sharedclassloader来加载,所以不应该把Spring的包放到Web应用的路径下,应该放到Tomcat指定的共享目录下

    
     10
  • Monday
    2019-07-08
    1、原文【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。

    
     8
  • Liam
    2019-07-04
    老师能讲下什么是上下文加载器吗,什么情况下会用到它?这个和双亲委派有关吗

    作者回复: 线程上下文加载器其实是线程私有数据,跟线程绑定的属性

     1
     5
  • Li Shunduo
    2019-07-10
    在其他地方看到过可以通过配置<Loader delegate="true"/>让tomcat遵循双亲委派,老师在答疑篇可以展开讲讲吗?

    作者回复: 是的,如果你不想Tomcat打破双亲委托,可以配这个参数

    
     4
  • QQ怪
    2019-07-05
    双亲委派模型其实不是叫单亲委派更好?

    作者回复: 还真是

    
     4
  • 妥协
    2019-07-04
    看到过这样一句话,一直没想明白:"类的唯一性由类加载器实例和类的全名一同确定的,即使同一串字节流由不同的类加载器加载,也是不同的实例" ,每个类加载器加载前都会判断是否已经加载过,同名的类判断加载过了,不是不会在加载吗?

    作者回复: 每个类记载“实例”只判断自己是否加载过

    
     4
  • 强哥
    2019-07-04
    每篇文章最后的总结,若能概括出这么做的意图及优点,这样对读者来说收益更大。

    作者回复: Servlet规范建议,全路径类名与系统类同名的话,优先加载web应用自己定义的类。

    
     4
  • Mq
    2019-07-04
    李老师,为什么要打破双亲委托

    作者回复: 文中其实有解释,servlet规范建议这么做

     1
     4
  • Monday
    2019-07-08
    如果能画出Tomcat类加载器打破与不打破双亲委托模式对比图,我想比文字更具说明性。
    
     3
  • 新世界
    2019-07-04
    由于沿用双亲委派重写findClass即可,找不到最后到固定目录下查找,不需要重写loadClass,还有一点不明白,tomcat为什么要打破双亲委派定义自己的classloader,不定义不行吗?

    作者回复: Servlet规定这样做的,优先加载web应用目录下的类,只要这个类不覆盖jre核心类

    
     3
  • 火凤凰
    2019-08-29
    老师,这边我有个疑问。tomcat 中的findClass方法里面首先是现在本地去查找要加载的类,找不到然后让父加载器去查找。然后在loadClass中,第四步调用findClass要加载的类的时候找不到,然后去调用第五步通过Class.forName()去加载尼?这一步是不是多余的?明明findClass方法应该包含了AppClassLoader需要查找的类吧?还望老师或者一起学习的大佬们解惑一下?

    作者回复: findclass只在本地应用目录下找,不包括AppClassLoader的加载路径

     2
     2
  • 吖蒲
    2019-08-08
    老师,我看源码了还是有点不懂,第三步骤tomcat的类加载器先用extclassloader加载类,ext让父加载器bootstrap去加载,防止优先加载应用中同名的类,那我用appclassloader,最终也能达到bootstrap加载器去加载类的效果,那为什么不直接调用appclassloader加载??

    作者回复: 好问题,appclassloader会加载PATH目录下的类,这样就达不到优先加载web应用目录下类的目的了

     1
     2
  • 飞翔
    2019-07-23
    老师 您说
    java 的类加载器,就是把字节码格式.class 文件加载到JVM的方法区,并在JVM的堆区建立一个java.lang.Class 对象实例

    那loadclass方法负责把字节码格式.class 文件加载到JVM的方法区
    和defineclass负责在JVM的堆区建立一个java.lang.Class 对象实例 这样理解对嘛


    展开

    作者回复: 对的

    
     2
  • Mr.差不多
    2019-07-05
    双亲委派规则是 当父加载器找不到此文件时才交给子加载器去加载。那么我觉得Tomcat重写loadClass方法其实也是这个逻辑。假设现在有一个类是需要在WebAppClassLoader加载的,那么它会先查询是否在AppClassLoader加载过,如果没有那么查看是否在ExtClassLoader加载过,那么这一系列步骤不就是为了保证没有在父加载器找不到此文件吗?这不还是双亲委派的模型吗?麻烦老师给解答下

    作者回复: WebAppClassLoader不会首先委托给AppClassLoader去加载,而是ExtClassLoader。这是根本区别

    
     2
  • nightmare
    2019-07-04
    我明白了,比如可以把多个项目共享的jar包放到${CATALINA_HOME}/shared目录下,让sharedclassloader来加载,并且是所有context的web应用共享的,而都有的放在web路径下,先让扩展类加载器加载,避免覆盖jre中的类,再让自定义的web加载器来加载独有的类,最后加载让应用加载器加载扩展类加载器和自定义加载器加载不到的类,谢谢李老师

    作者回复: 👍

     1
     2
  • Jialin
    2019-12-22
    课后题思考,应该只需要重写findClass方法,findClass方法和loadClass方法区别在于:findClass方法负责具体的类加载细节,主要职责就是找到“.class”文件,可能来自文件系统或者网络,找到后把“.class”文件读到内存得到字节码数组,然后调用 defineClass 方法得到 Class 对象。而loadClass方法只是保证双亲委派机制运行流程,先看当前类是否被加载,若没有没加载交由父级类加载器加载,父类加载器加载失败由当前类加载器加载
    
     1
  • Nu11PointerEx
    2019-07-19
    这里有个疑问,
    原文【没有一上来就直接委托给父加载器,而是先在本地目录下加载,为了避免本地目录下的类覆盖 JRE 的核心类,先尝试用JVM 扩展类加载器 ExtClassLoader 去加载】
    如果本地目录定义了与核心库同样的类名,这样就无法保证安全了吧?

    作者回复: Tomcat的类加载器首先尝试用ExtClassLoader去加载,目的就是为了避免你说的这个问题,一旦ExtClassLoader已经加载过了,本地的同名类就不会被加载。

    
     1
  • 🐟🐙🐬🐆🦌...
    2019-07-11
    老师 我想问下 App类加载器的类 为什么可以访问 由Ext类加载器加载的类和根类加载器加载的类。 不是不同的类加载器加载的类相互隔离么 .App类加载器和ext类加载器 和根类加载器都是不同类加载器啊。双亲委托机制是为了让类不重复加载和避免jvm类被破坏而已。那怎么说双器委派机制后 ,App类加载器可以访问Ext加载的类.不是命名空间隔离了么

    作者回复: 所谓的隔离是说同一个类加载器的不同实例加载的同名类,被认为是两个不同的类。注意说的是不同实例。

    appclassloder不会跟它的父加载器加载同名的类,也就不存在隔离的说法。

    
     1
  • WL
    2019-07-04
    想问一下老师tomcat为什么采用"首先自己尝试去加载某个类,如果找不到再代理给父类加载", 这种方式呢, 我不是很理解. 还有在Tomcat的类加载器的loadClass()方法, 会先调用ExtClassLoader加载类, 然后才调用findClass(name), 这是不是与上面的"首先自己尝试去加载某个类,如果找不到再代理给父类加载"这句话矛盾呢?

    作者回复: 不矛盾的,本质还是自己先加载,这里先委托给Ext加载器纯粹为了避免类覆盖

    
     1
我们在线,来聊聊吧