https://time.geekbang.org/column/intro/180
一般类加载是双亲委派,避免自定义类覆盖jvm基础类库,保证安全性 Application(CLASSPATH) -> Extension(Java_Home /lib/ext) -> Bootstrap(Java_Home/lib)
加载器之间的关系保持是通过持有父类引用
findClass 字节数组加载
defineClass 类字节码到对象
loadClass是双亲委托类加载器加载,默认的双亲委派
Tomcat的类加载器WebAppClassLoader先自己加载,重写findClass/loadClass没有再委托给Ext加载(防止自己的类覆盖核心类库)
问题1:tomcat同时部署多个应用,如何隔离? 每个web应用创建一个类加载器
问题2:tomcat多个应用如何共享部分公用Jar? WebAppClassLoader委托SharedClassLoader 去加载这个类,SharedClassLoader 会在指定目录下加载共享类,之后返回给 WebAppClassLoader
问题3:如何隔离 Tomcat 本身的类和 Web 应用的类? CatalinaClassLoader,专门来加载 Tomcat 自身的类
增加CommonClassLoader,作为 CatalinaClassLoader 和 SharedClassLoader 的父加载器。CommonClassLoader 能加载的类都可以被 CatalinaClassLoader 和 SharedClassLoader 使用,而 CatalinaClassLoader 和 SharedClassLoader 能加载的类则与对方相互隔离。WebAppClassLoader 可以使用 SharedClassLoader 加载到的类,但各个 WebAppClassLoader 实例之间相互隔离
在 JVM 的实现中有一条隐含的规则,默认情况下,如果一个类由类加载器 A 加载,那么这个类的依赖类也是由相同的类加载器加载,如何突破此条限制?
类加载器保存在线程私有数据里,只要是同一个线程,一旦设置了线程上下文加载器,在线程后续执行过程中就能把这个类加载器取出来用。因此 Tomcat 为每个 Web 应用创建一个 WebAppClassLoader 类加载器,并在启动 Web 应用的线程里设置线程上下文加载器,这样 Spring 在启动时就将线程上下文加载器取出来,用来加载 Bean