Tomcat类加载

tomcat如何实现,应用隔离类加载?

org.apache.catalina.loader.WebappClassLoaderBase#loadClass(java.lang.String, boolean)
(1)先在本地缓存中查找是否已经加载过该类(对于一些已经加载了的类,会被缓存在resourceEntries这个数据结构中),如果已经加载即返回,否则 继续下一步。 (2)让系统类加载器(AppClassLoader)尝试加载该类,主要是为了防止一些基础类会被web中的类覆盖,如果加载到即返回,返回继续。 (3)前两步均没加载到目标类,那么web应用的类加载器WebAppClassLoader将自行加载,如果加载到则返回,否则继续下一步。 (4)最后还是加载不到的话,则委托父类加载器(Common ClassLoader)去加载。
违反了双亲委托原则的,对于一些未加载的非基础类(Object,String等),各个web应用自己的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给commonClassLoader走双亲委托。
WebappClassLoaderBase#findClass
  1. 首先尝试在自己应用目录下查找要加载的类
  2. 没有找到,交给父加载器查找
CommonClassLoader、CatalinaClassLoader、SharedClassLoader、WebAppClassLoader是Tomcat自定义的类加载器,它们分别加载/common/*、/server/*、/shared/*、/WEB-INF/*中的类库
对于Tomcat的6.x版本,只有指定了tomcat/conf/catalina.properties配置文件的server.loader和shared.loader项后才会真正建立CatalinaClassLoader和SharedClassLoader的实例,否则会用到这两个类的地方都会用CommonClassLoader的实例代替,而默认的配置文件中没有设置这两个项。所以Tomcat6.x顺理成章地把/common、/shared和/server三个目录合并成了一个/lib目录,这个目录里的类库相当于以前的/common目录中类库的作用。这是Tomcat设计团队为了简化大多数的部署场景所做的一项改进,如果默认的设置不能满足需求,用户可以通过修改配置文件指定server.loader和shared.loader的方式重新启动Tomcat5.x的类加载器架构。

1. WebAppClassLoader

Tomcat 的解决方案是自定义一个类加载器 WebAppClassLoader, 并且给每个 Web 应用创建一个类加载器实例。我们知道,Context 容器组件对应一个 Web 应用,因此,每个 Context容器负责创建和维护一个 WebAppClassLoader加载器实例。这背后的原理是,不同的加载器实例加载的类被认为是不同的类,即使它们的类名相同。这就相当于在 Java 虚拟机内部创建了一个个相互隔离的 Java 类空间,每一个 Web 应用都有自己的类空间,Web 应用之间通过各自的类加载器互相隔离。

2.SharedClassLoader

本质需求是两个 Web 应用之间怎么共享库类,并且不能重复加载相同的类。在双亲委托机制里,各个子加载器都可以通过父加载器去加载类,那么把需要共享的类放到父加载器的加载路径下不就行了吗。
因此 Tomcat 的设计者又加了一个类加载器 SharedClassLoader,作为 WebAppClassLoader的父加载器,专门来加载 Web 应用之间共享的类。如果 WebAppClassLoader自己没有加载到某个类,就会委托父加载器 SharedClassLoader去加载这个类,SharedClassLoader会在指定目录下加载共享类,之后返回给 WebAppClassLoader,这样共享的问题就解决了。

3. CatalinaClassloader

如何隔离 Tomcat 本身的类和 Web 应用的类?
要共享可以通过父子关系,要隔离那就需要兄弟关系了。兄弟关系就是指两个类加载器是平行的,它们可能拥有同一个父加载器,基于此 Tomcat 又设计一个类加载器 CatalinaClassloader,专门来加载 Tomcat 自身的类。
这样设计有个问题,那 Tomcat 和各 Web 应用之间需要共享一些类时该怎么办呢?

4. CommonClassLoader

老办法,还是再增加一个 CommonClassLoader,作为 CatalinaClassloader和 SharedClassLoader的父加载器。CommonClassLoader能加载的类都可以被 CatalinaClassLoader和 SharedClassLoader使用。

 

 

 

 

 

 

 

 
 
posted on 2023-03-19 20:37  zhengbiyu  阅读(99)  评论(0编辑  收藏  举报