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应用程序的独立性和隔离性,避免了类库冲突,并使得每个应用程序可以拥有自己的类和库版本。

相关推荐
宸津-代码粉碎机3 小时前
OpenAI 连夜迎战 Grok Bot 和 Muse:AI 智能体从 “会聊天” 到 “能办事”,现在入场还来得及吗
java·大数据·人工智能·分布式·python
噢,我明白了5 小时前
java中唯一键和幂等键的应用
java·后端
程序猿乐锅5 小时前
【黑马点评 | 第八篇】Redisson分布式锁
java·数据库·spring boot·redis·分布式·spring·缓存
考虑考虑5 小时前
synchronized字符串常量
java·后端·java ee
长谷深风1115 小时前
Tool与Skill:AI能力设计的分水岭
java·人工智能·ai·大模型·aiagent
m0_587383005 小时前
广州24小时自助健身房解决方案实战指南与系统部署要点
java·spring·小程序·架构·需求分析
Escalating_xu5 小时前
【C 语言】深入理解指针(1·下):指针运算、野指针、assert 与传址实战
java·c语言·开发语言
周杰偷奶茶6 小时前
【Java】数据类型与变量
java·开发语言
code斗6 小时前
Java数据结构:堆详解
java·开发语言·数据结构
重生之小比特6 小时前
【C++进阶】map和set
java·开发语言·c++