Tomcat为什么打破双亲委派模型(基于官方文档)

先看Servlet规范2.4版中9.7.2章节的一段话

翻译:

一个容器用于加载 WAR 文件中的 Servlet 的类加载器必须允许开发者按照 J2SE 的标准方式使用 getResource 方法加载 WAR 中库 JAR 文件内的任何资源。但它不能允许 WAR 覆盖 J2SE 或 Java Servlet API 的类。建议该加载器不允许 WAR 中的 Servlet 访问 Web 容器的实现类。同时,建议应用程序类加载器实现时优先加载 WAR 内的类和资源,而不是加载容器范围内的库 JAR 文件中的类和资源。 

Tomcat为什么打破双亲委派模型

先看总结

Tomcat打破双亲委派模型的主要原因是为了解决Web应用程序的类加载冲突问题,并提供更好的灵活性和可扩展性。双亲委派模型在一般情况下是有益的,可以确保类加载的安全性和一致性,但在Web应用程序的场景下,它可能会导致一些问题:

1. 类加载冲突: Web应用程序通常需要依赖一些共享的类库,这些类库可能由容器提供或者由应用程序自身提供。当使用双亲委派模型时,容器的类加载器会先尝试加载共享类库,导致Web应用程序中提供的同名类无法被正确加载,从而产生类加载冲突。

2. 限制灵活性:双亲委派模型要求类加载器在委派给父加载器之前尝试加载类,这可能会限制Web应用程序自定义类加载的灵活性。有些Web应用程序可能需要加载自定义的类或资源,而不希望受到容器类加载器的限制。

为了解决这些问题,Tomcat采用了自定义的Web应用程序类加载器,它打破了双亲委派模型的一部分规则,具体表现在:

1. Web应用程序类加载器首先会查找Web应用程序内部的类和资源,而不是立即委派给父类加载器。这样可以确保Web应用程序中提供的类能够被正确加载,避免类加载冲突。

2. 对于JRE基本类(如Java标准库类),Web应用程序类加载器不能覆盖。这是为了保证Java核心类的一致性和稳定性。

3. 对于JavaEE API类(如Servlet、JSP、EL、WebSocket等),Web应用程序类加载器会先委派给父类加载器加载,确保使用Tomcat实现的JavaEE规范。

通过打破双亲委派模型的一部分规则,Tomcat提供了更灵活的类加载策略,允许Web应用程序自定义类加载器加载自己的类和资源,避免了类加载冲突问题,同时确保了Java核心类的稳定性和JavaEE规范的正确实现。这样的设计使得Tomcat能够更好地支持各种复杂的Web应用程序,并提供了更高的可扩展性和自定义能力。

详细如下^{}^{[1]}

 这是官方的一幅图,接下来介绍里面各个加载器的作用

  • Bootstrap — 该类加载器包含 Java 虚拟机提供的基本运行时类,以及系统扩展目录 ( $JAVA_HOME/jre/lib/ext) 中存在的 JAR 文件中的任何类。 注意:某些 JVM 可能会将其实现为多个类加载器,或者它可能根本不可见(作为类加载器)。

  • System— 该类加载器通常从环境变量的内容初始化CLASSPATH。所有这些类对于 Tomcat 内部类和 Web 应用程序都是可见的。但是,标准 Tomcat 启动脚本($CATALINA_HOME/bin/catalina.sh或 %CATALINA_HOME%\bin\catalina.bat)完全忽略环境变量本身的内容CLASSPATH,而是从以下存储库构建系统类加载器

    • $CATALINA_HOME/bin/bootstrap.jar

    • $CATALINA_BASE/bin/tomcat-juli.jar或 $CATALINA_HOME/bin/tomcat-juli.jar 

    • $CATALINA_HOME/bin/commons-daemon.jar

  • Common — 该类加载器包含其他类,这些类对 Tomcat 内部类和所有 Web 应用程序都可见。

    通常,应用程序类不应放置 在这里。该类加载器搜索的位置由 $CATALINA_BASE/conf/catalina.properties 中的属性定义common.loader。默认设置将按列出的顺序搜索以下位置:

    • 解压后的类和资源$CATALINA_BASE/lib
    • JAR 文件位于$CATALINA_BASE/lib
    • 解压后的类和资源$CATALINA_HOME/lib
    • JAR 文件位于$CATALINA_HOME/lib
  • WebappX — 为部署在单个 Tomcat 实例中的每个 Web 应用程序创建一个类加载器。/WEB-INF/classesWeb 应用程序目录中的所有解压类和资源,以及/WEB-INF/libWeb 应用程序目录下 JAR 文件中的类和资源,对此 Web 应用程序可见,但对其他应用程序不可见。

 翻译:

如上所述,Web 应用程序类加载器与默认的 Java 委托模型不同(根据 Servlet 规范 2.4 版第 9.7.2 Web 应用程序类加载器第 9.7.2 节中的建议)。当处理从 Web 应用程序的WebappX类加载器加载类的请求时,该类加载器将首先在本地存储库中查找,而不是在查看之前进行委托。但也有例外。作为 JRE 基类一部分的类不能被覆盖。有一些例外,例如可以使用适当的 JVM 功能覆盖 XML 解析器组件,该功能是 Java <= 8 的认可标准覆盖功能和 Java 9+ 的可升级模块功能。最后,Web 应用程序类加载器将始终首先委托 Tomcat 实现的规范(Servlet、JSP、EL、WebSocket)的 JavaEE API 类。Tomcat 中的所有其他类加载器都遵循通常的委托模式。

因此,从 Web 应用程序的角度来看,类或资源加载按以下顺序查找以下存储库:

  • JVM 的引导类
  • /WEB-INF/您的 Web 应用程序的类
  • Web 应用程序的/WEB-INF/lib/*.jar
  • 系统类加载器类(如上所述)
  • 常见的类加载器类(如上所述)

来自:

[1]. Apache Tomcat8(8.5.91)  Class Loader How-To

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值