java - 为什么更改 WEB-INF/lib 中 jar 文件的目录顺序会导致 Tomcat 8 中出现 NoClassDefFoundError?

标签 java maven tomcat centos7 tomcat8

我们有一个在 Tomcat 8 中运行的 Web 应用程序,最近我们观察到我们团队中一些开发人员构建的 Artifact (.war 文件)抛出一个 NoClassDefFoundError,而同样的其他人构建的代码按预期运行。

来自 logs/localhost.2018-05-11.log:

org.jboss.resteasy.spi.UnhandledException: java.lang.NoClassDefFoundError: Could not initialize class org.geotools.referencing.datum.DefaultEllipsoid
    ...
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.geotools.referencing.datum.DefaultEllipsoid
    at org.geotools.referencing.GeodeticCalculator.<init>(GeodeticCalculator.java:277)
    ...

有时,但并非总是,伴随(之前)有:

org.jboss.resteasy.spi.UnhandledException: java.lang.IncompatibleClassChangeError: Implementing class
    ...

检查 war 文件,工作 Artifact 和损坏 Artifact 的内容似乎相同,但有一个明显的异常(exception),WEB-INF/lib 中 jar 文件的“目录顺序”不同。

对展开的war文件执行以下过程并重新启动Tomcat似乎消除了异常:

$ # jars in "bad" order
$ ls -U WEB-INF/lib
x.jar
b.jar
y.jar
a.jar
c.jar
z.jar
$ cp -p WEB-INF/lib/* /tmp/lib/
$ rm -r WEB-INF/lib
$ mv /tmp/lib WEB-INF/lib
$ # jars in "good" order (appears to be alphabetical after a 'cp' on my system)
$ ls -U WEB-INF/lib
a.jar
b.jar
c.jar
x.jar
y.jar
z.jar

“好” war 没有按字母顺序排列的 jar ,但似乎有许多“好”订单和许多“坏”订单。

我最初认为我们可能在不同的 jar 中有多个版本的 DefaultEllipsoid 类,导致正确版本和另一个版本之间出现竞争条件,但事实似乎并非如此。

p>

我在 tomcat 中启用了详细的类加载器调试,在这两种情况下,logs/catalina.out 显示此类正在从正确的 jar 中加载:

[Loaded org.geotools.referencing.datum.DefaultEllipsoid from file: /opt/tomcat/temp/1-webapp/WEB-INF/lib/gt-referencing-11.4.jar]

知道这里会发生什么吗?

详细信息:

  • 中央操作系统 7
  • Apache Tomcat/8.0.43
  • Java 1.8.0_144
  • Apache Maven 3.3.9

最佳答案

行:

Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.geotools.referencing.datum.DefaultEllipsoid

表示类 DefaultEllipsoid 已找到但有效,还有一些其他类 需要加载但失败。另一个类无效。

这个类可能与两个非常不同的版本重复,或者一个版本用于编译,另一个版本在运行时具有不同的方法签名。

此外,从 tomcat8 开始,WEB-INF/lib 中的应用程序 jar 文件不再按字母顺序加载。我认为在 tomcat 站点上有一个文档,但现在我找不到它了,但我在 tomcat bugzilla bug 57129 上发现了一个回归错误(无法修复)

这个类加载器的东西意味着,如果你改变了 WEB-INF/lib 上的一些东西并重新启动 Tomcat,那么就会有一些随机类加载使你的应用程序以一种或另一种方式加载如果有重复的 jar 版本。

总结一下:检查 DefaultEllipsoid 导入并检查这些类是否有重复项。您的构建还需要清理以使用与运行时相同的版本(我希望您使用像 maven 这样的工具来进行构建)

关于java - 为什么更改 WEB-INF/lib 中 jar 文件的目录顺序会导致 Tomcat 8 中出现 NoClassDefFoundError?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50294927/

相关文章:

java - Kafka 消息版本控制

java - 如何在SWT中将屏幕分成3部分?

java - Spring Boot Maven 不会构建可执行 Jar,因为它发现重复项

java - Sonatype nexus 下载的 jars 位置

tomcat - 将war文件放到tomcat服务器后如何启动netbeans项目?

tomcat - 如何使用现有的 CSR 在 Tomcat 上安装 SSL 证书?

java.net.bindexception地址已经在多台tomcat上运行

java - hive jdbc client 和 hive metastore java api 有什么区别?

Java web启动权限问题?

Maven 跳过测试