Tomcat打破双亲委派模型的方式

文章目录

1、前言

双亲委派模型是一种类加载机制,它确保了类加载器层次结构中的父加载器先于子加载器尝试加载类。这种机制有助于防止类的重复加载和类之间的不兼容。

然而,为了支持Web应用程序的独立性和隔离性,Tomcat需要在某些情况下打破这一原则。

2、标准的双亲委派模型

在标准的双亲委派模型中,类加载器按以下顺序尝试加载类:

  • Bootstrap ClassLoader:引导类加载器,负责加载Java核心类库($JAVA_HOME/jre/lib)。
  • Extension ClassLoader:扩展类加载器,负责加载Java扩展库($JAVA_HOME/jre/lib/ext)。
  • Application ClassLoader:应用类加载器,负责加载应用程序的类路径(classpath)上的类。

子类加载器在加载类时,先请求父加载器加载,只有当父加载器找不到时,子类加载器才会尝试自己加载。

3、Tomcat的类加载器架构

Tomcat为了支持多个Web应用程序的独立性,设计了一套复杂的类加载器架构,主要包括以下几个类加载器:

  • Bootstrap ClassLoader:加载JVM核心类。
  • System ClassLoader:加载Tomcat自身的类和库(位于$CATALINA_HOME/lib)。
  • Common ClassLoader:加载共享库(位于$CATALINA_HOME/lib)。
  • Webapp ClassLoader:每个Web应用都有自己的类加载器,负责加载Web应用程序的类和库(位于WEB-INF/classes和WEB-INF/lib)。

4、Tomcat打破双亲委派模型的方式

Tomcat通过自定义类加载器的实现,允许Web应用程序在加载类时打破双亲委派模型。这种机制允许Web应用程序优先加载自己的类和库,而不是依赖父加载器。这种行为主要通过WebappClassLoader来实现。

具体实现:

WebappClassLoader:Tomcat为每个Web应用创建一个WebappClassLoader实例。这个类加载器会首先尝试从WEB-INF/classes和WEB-INF/lib中加载类,而不是先委派给父加载器。

双亲委派的打破:

当WebappClassLoader加载类时,它会检查是否在其自己的类路径中存在。如果存在,它会直接加载,而不是委派给父加载器。

这种机制通过在WebappClassLoader的loadClass方法中覆盖默认的双亲委派行为实现。

例如:org.apache.catalina.loader.WebappClassLoaderBase类中的findClass方法实现了优先从Web应用程序的类路径加载类。

示例代码:

以下是WebappClassLoader如何打破双亲委派模型的简化示例:

java 复制代码
public class WebappClassLoader extends URLClassLoader {

    private ClassLoader parent;

    public WebappClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, null); // 将父加载器设置为null
        this.parent = parent;
    }

    @Override
    public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        // 首先,检查是否已经加载了类
        Class<?> clazz = findLoadedClass(name);
        if (clazz == null) {
            try {
                // 尝试从Web应用的类路径中加载类
                clazz = findClass(name);
            } catch (ClassNotFoundException e) {
                // 如果找不到,再委派给父加载器加载
                clazz = parent.loadClass(name);
            }
        }
        if (resolve) {
            resolveClass(clazz);
        }
        return clazz;
    }
}

在这个示例中,WebappClassLoader首先尝试通过findClass方法加载类,如果找不到再委派给父加载器。这种方式打破了双亲委派模型,使得Web应用程序可以优先加载自己的类。

5、总结

Tomcat通过自定义的WebappClassLoader打破了双亲委派模型,允许Web应用程序优先加载自己的类和资源。这种机制确保了每个Web应用程序的独立性和隔离性,避免了类库冲突,并使得每个应用程序可以拥有自己的类和库版本。

相关推荐
Bug收容所3 分钟前
12305项目学习day5
java·spring boot·redis·mysql·spring·rocketmq
::呵呵哒::4 分钟前
java中SseEmitter
java·开发语言
lichuangcsdn5 分钟前
【Spring AI 学习(三)】实现简单的对话
java·人工智能·学习·spring·spring ai
长不胖的路人甲13 分钟前
Spring Bean 完整生命周期
java·spring·rpc
青石路22 分钟前
记一次Qoder排查mave-shade-plugin只重定向部分package导致的NoSuchMethodError问题,查的还挺快的
java·maven
墨神谕1 小时前
认识一下Unicode(统一码)
android·java·数据库
宸津-代码粉碎机1 小时前
Jar热部署进阶实战|修复原生方案OOM与类冲突问题,生产级无BUG优化方案
java·大数据·服务器·开发语言·前端·人工智能·python
小Ti客栈12 小时前
Spring Boot 集成 Springdoc-OpenAPI 与 Knife4j实现接口文档与可视化调试
java·spring boot·后端
Ai拆代码的曹操12 小时前
Spring 事务 REQUIRES_NEW 嵌套调用:连接池翻倍的秘密
java·后端·spring
动恰客流统计13 小时前
ReID边缘计算视觉统计:餐饮店客流增长的数字化破局路径
java·大数据·运维·人工智能