首页 > 技术文章 > tomcat 是如何做到不同webapp 类隔离的

kevin7234 2019-04-03 21:00 原文

 这个问题的核心是classloader 

 

上图中 启动类加载器,扩展类加载器,应用程序类加载器是 jvm 自带的类加载器.

 

comm  catalina  shared webapp 是tomcat 扩展的加载器,他们分别加载 /common/*/server/*/shared/*

WebAppClassLoader 负载加载  webapp 目录的jar 和 class .

WebAppClassLoader  没有遵循双亲委托模式,他的具体加载逻辑如下:

 

第1步:检查当前class loader 的缓存resourceEntries,是否已经加载,如果有直接返回。

第2步:检查 jvm 自带加载器是否加载过。

第3步:尝试用  javaseClassLoader 去加载,为什么要做这个尝试呢,防止代码重写了java.lang.String  等jdk核心类,从而导致异常。

第4步:如果设置了双亲委托模式 delegateLoad=true ,尝试用父加载器加载。

第5步: 尝试从当前classloader 制定的目录中加载,同时会将加载信息放到缓存中 resourceEntries

这样就实现了资源隔离。

 

扩展信息:

1.通过gc 回收class loader ,从而可以实现回收class,重新创建classloader,然后重新load class ,从而达到不重启jvm更新class的目的(热更新),jsp 的热更新就是这么干的。

 

 2. jvm instrumentation 机制可以通过agent,去修改正在运行中的已加载的class 对象,该方法很有用,比如生产环境出了问题,重启后问题无法复现,那么就可以在线增加日志排错.

阿里巴巴基于该原理开发了一个强大在线调试工具: https://github.com/alibaba/arthas

 

3. ClassFileTransformer  利用tranformer 和 class loader 可以实现很多很神奇的功能,比如所有controller 方法第一行打印出请求参数,实现这个目的可以用spring AOP,同时也可以用ClassFileTransformer。

groovy 通过大量的 ClassFileTransformer 修改了很多jdk 核心class 的方法.

 

 

相关资源:

1.https://blog.csdn.net/sdmjhca/article/details/77716899

2.https://www.cnblogs.com/aspirant/p/8991830.html  

 

推荐阅读