基于本文回答
0
评论

WEB-INF/lib 和 WEB-INF/classes 下的类,哪个加载优先级更高?

知识点图片

结论:WEB-INF/classes 的加载优先级高于 WEB-INF/lib

如果同一个类(全限定名相同,例如 com.example.MyClass)同时存在于 WEB-INF/classes 目录下的 .class 文件中,和 WEB-INF/lib 目录下的某个 .jar 包中,Web 容器(如 Tomcat、Jetty)会优先加载 WEB-INF/classes 下的类

详细解释

根据 Java Servlet 规范(Servlet Specification),Web 应用程序类加载器(WebAppClassLoader)建议的加载顺序如下:

  1. Bootstrap 类:首先检查 JVM 的核心类(如 java.lang.String),这些类永远不能被覆盖。
  2. WEB-INF/classes:接着加载 Web 应用自身的编译类文件。
  3. WEB-INF/lib/*.jar:最后加载 Web 应用引用的第三方 JAR 包。

为什么这样设计?

这种设计主要是为了方便开发打补丁(Hotfix)

  • 覆盖第三方库的 Bug:如果你引用的某个开源 JAR 包里有一个类有 Bug,你不需要重新编译打包整个 JAR。你只需要把修改后的该类的 .class 文件放在 WEB-INF/classes 对应的包路径下,容器就会优先加载你修改后的类,从而“屏蔽”掉 JAR 包里有 Bug 的类。
  • 开发调试:在开发过程中,IDE 编译的代码通常输出到 classes 目录,这样可以确保你运行的是最新编写的代码,而不是旧的 JAR 包代码。

特殊情况说明 (Tomcat 为例)

虽然 Servlet 规范推荐了上述顺序,但具体的类加载行为还涉及到双亲委派模型(Parent Delegation Model)的配置。

在 Tomcat 中,默认行为(delegate="false")如下:

  1. Bootstrap 类(JVM 基础类)。
  2. WEB-INF/classes
  3. WEB-INF/lib/*.jar
  4. Common 类加载器(Tomcat 全局库)。

即使你开启了 delegate="true"(强制遵循标准的 Java 双亲委派,即先查父加载器),这个顺序只会影响“Web 应用”与“Tomcat 全局库/系统库”之间的优先级。在 Web 应用内部,classes 永远优先于 lib

右滑查看面试常问