tomcat类加载器

Java默认的类加载机制是通过双亲委派模型来实现的。而Tomcat实现的方式又和双亲委派模型有所区别。原因在于一个Tomcat容器允许同时运行多个Web程序,每个Web程序依赖的类又必须是相互隔离的。因此,如果Tomcat使用双亲委派模式来加载类的话,将导致Web程序依赖的类变为共享的。
双亲委派模式

Java是一门面向对象的语言,而对象又必然依托于类。类要运行,必须首先被加载到内存。我们可以简单地把类分为几类:

1.Java自带的核心类

2.Java支持的可扩展类

3.我们自己编写的类

如果所有的类都使用一个类加载器来加载,会出现什么问题呢?

假如我们自己编写一个类java.util.Object,它的实现可能有一定的危险性或者隐藏的bug。而我们知道Java自带的核心类里面也有java.util.Object,如果JVM启动的时候先行加载的是我们自己编写的java.util.Object,那么就有可能出现安全问题!

所以,Sun(后被Oracle收购)采用了另外一种方式来保证最基本的、也是最核心的功能不会被破坏。你猜的没错,那就是双亲委派模式!

双亲委派模式对类加载器定义了层级,每个类加载器都有一个父类加载器。在一个类需要加载的时候,首先委派给父类加载器来加载,而父类加载器又委派给祖父类加载器来加载,以此类推。如果父类及上面的类加载器都加载不了,那么由当前类加载器来加载,并将被加载的类缓存起来。
在这里插入图片描述

1.java自带的核心类 -- 由启动类加载器加载

2.Java支持的可扩展类 -- 由扩展类加载器加载

3.我们自己编写的类 -- 默认由应用程序类加载器或其子类加载

双亲委派模型解决了类错乱加载的问题,也设计得非常精妙。但它也不是万能的,在有些场景也会遇到它解决不了的问题。哪些场景呢?我们举一个例子来看看。

在Java核心类里面有SPI(Service Provider Interface),它由Sun编写规范,第三方来负责实现。SPI需要用到第三方实现类。如果使用双亲委派模型,那么第三方实现类也需要放在Java核心类里面才可以,不然的话第三方实现类将不能被加载使用。但是这显然是不合理的!怎么办呢?ContextClassLoader(上下文类加载器)就来解围了。

在java.lang.Thread里面有两个方法,get/set上下文类加载器

1.public void setContextClassLoader(ClassLoader cl)

2.public ClassLoader getContextClassLoader()

我们可以通过在SPI类里面调用getContextClassLoader来获取第三方实现类的类加载器。由第三方实现类通过调用setContextClassLoader来传入自己实现的类加载器。这样就变相地解决了双亲委派模式遇到的问题。但是很显然,这种机制破坏了双亲委派模式。

Tomcat类加载机制

在这里插入图片描述

Tomcat类加载图
我们在这张图中看到很多类加载器,除了Jdk自带的类加载器,我们尤其关心Tomcat自身持有的类加载器。仔细一点我们很容易发现:Catalina类加载器和Shared类加载器,他们并不是父子关系,而是兄弟关系。为啥这样设计,我们得分析一下每个类加载器的用途,才能知晓。

1.Common类加载器,负责加载Tomcat和Web应用都复用的类
2.Catalina类加载器,负责加载Tomcat专用的类,而这些被加载的类在Web应用中将不可见
3.Shared类加载器,负责加载Tomcat下所有的Web应用程序都复用的类,而这些被加载的类在Tomcat中将不可见
4.WebApp类加载器,负责加载具体的某个Web应用程序所使用到的类,而这些被加载的类在Tomcat和其他的Web应用程序都将不可见
5.Jsp类加载器,每个jsp页面一个类加载器,不同的jsp页面有不同的类加载器,方便实现jsp页面的热插拔

链接:https://www.jianshu.com/p/51b2c50c58eb

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值