为什么 java.lang.NoSuchMethodError 发生非常特定于环境或 class 加载程序?

Why java.lang.NoSuchMethodError occure very specific to environment or class loader?

我目前正在处理一个项目,我们有 log4j-over-slf4j.jar 文件。在所有环境中,这个罐子都在工作。但是突然间我有了一个 WebSphere 应用服务器。 我们的产品在 tomcat 服务器上运行,突然间我们的应用程序无法创建任何日志,而它正在另一个环境中创建。如果我尝试从项目中删除该 jar,那么我就可以生成日志。

但我无法确定为什么我应该只针对这个特定环境执行此操作。

或者我应该怎么做才能在服务器运行时识别class加载器信息来识别加载了哪个class或加载了哪个方法?

我的 jdk 版本是:“1.7.0_71”

我的应用程序包含这些库:

antlr-2.7.7.jar
aopalliance-1.0.jar
asm-1.5.3.jar
asm-attrs-1.5.3.jar
axiom-api-1.2.12.jar
axiom-impl-1.2.12.jar
axis2-1.6.2.jar
axis2-kernel-1.6.1.jar
axis2-transport-http-1.6.1.jar
axis2-transport-local-1.6.1.jar
c3p0-0.9.2.1.jar
cglib-2.1_3.jar
com.ibm.jbatch-tck-spi-1.0.jar
commons-codec-1.6.jar
commons-collections-3.1.jar
commons-fileupload-1.2.jar
commons-httpclient-3.1.jar
commons-logging-1.1.3.jar
dom4j-1.6.1.jar
ehcache-1.2.3.jar
geronimo-activation_1.1_spec-1.0.2.jar
geronimo-javamail_1.4_spec-1.6.jar
geronimo-jta_1.1_spec-1.1.jar
geronimo-stax-api_1.0_spec-1.0.1.jar
geronimo-ws-metadata_2.0_spec-1.1.2.jar
hibernate-3.2.4.ga.jar
hibernate-annotations-3.3.0.ga.jar
hibernate-commons-annotations-3.1.0.GA.jar
hibernate-core-3.3.0.CR2.jar
hibernate-ehcache-3.3.0.CR2.jar
hibernate-entitymanager-3.3.1.ga.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar
hibernate-validator-3.1.0.CR2.jar
httpcore-4.0.jar
javaetmoi-spring4-vfs2-support-1.4.0.jar
javassist-3.18.1-GA.jar
javassist-3.3.GA.jar
javax.batch-api-1.0.jar
javax.servlet-api-3.0.1.jar
jaxen-1.1.1.jar
jboss-common-core-2.0.4.GA.jar
jboss-logging-3.3.0.Final.jar
jettison-1.2.jar
jsr311-api-1.0.jar
jta-1.1.jar
log4j-1.2.17.jar
log4j-api-2.0.jar
logkit-1.0.1.jar
mchange-commons-java-0.2.3.4.jar
neethi-3.0.1.jar
oracle-ojdbc6-11.2.0.3.0.jar
persistence-api-1.0.jar
poi-3.9.jar
slf4j-api-1.7.11.jar
slf4j-simple-1.6.4.jar
spring-aop-3.2.13.RELEASE.jar
spring-batch-core-3.0.1.RELEASE.jar
spring-batch-infrastructure-3.0.1.RELEASE.jar
spring-beans-3.2.13.RELEASE.jar
spring-context-3.2.13.RELEASE.jar
spring-core-3.2.13.RELEASE.jar
spring-expression-3.2.13.RELEASE.jar
spring-jdbc-3.2.13.RELEASE.jar
spring-orm-3.2.13.RELEASE.jar
spring-retry-1.0.3.RELEASE.jar
spring-tx-3.2.13.RELEASE.jar
spring-web-4.0.3.RELEASE.jar
stax-api-1.0.1.jar
woden-api-1.0M9.jar
woden-impl-commons-1.0M9.jar
woden-impl-dom-1.0M9.jar
wsdl4j-1.6.2.jar
wstx-asl-3.2.9.jar
xmlbeans-2.5.0.jar
xmlpull-1.1.3.1.jar
XmlSchema-1.4.7.jar
xpp3_min-1.1.4c.jar
xstream-1.4.7.jar

我的 tomcat lib 目录包含:

annotations-api.jar
catalina-ant.jar
catalina-ha.jar
catalina.jar
catalina-storeconfig.jar
catalina-tribes.jar
ecj-4.5.jar
el-api.jar
jasper-el.jar
jasper.jar
jsp-api.jar
ojdbc6-11.2.0.3.jar
servlet-api.jar
sqljdbc4-11.1.0.7.0.jar
tomcat-api.jar
tomcat-coyote.jar
tomcat-dbcp.jar
tomcat-i18n-es.jar
tomcat-i18n-fr.jar
tomcat-i18n-ja.jar
tomcat-jdbc.jar
tomcat-jni.jar
tomcat-juli.jar
tomcat-util.jar
tomcat-util-scan.jar
tomcat-websocket.jar
websocket-api.jar

不确定确切的环境,但我几乎可以肯定您正在加载某些库的意外版本 class。如果在从 Tomcat 切换到 WebSphere(或其他方式)后出现问题,可能是他们有不同版本的 slf4 相关的东西(或者其中一个有一个库,另一个缺少)。大多数时候 java 的 -verbose:class 选项应该可用于挖掘 class 从

加载的内容

当您的代码是使用与您的环境提供的不同版本的代码编译时,您会遇到此类错误。

public class A{
 public void a(){
 }
}

//newer version of module
public class AVariant{
 public void a(String b){
 }
}

我不太熟悉 WebSphere,但这里的问题是 WebSphere 使用 older/newer 或版本的日志记录框架,它与您编译应用程序的版本不兼容。您需要解决此依赖冲突。

本指南可以帮助您: https://www.slf4j.org/legacy.html

NoSuchMethod 错误发生在当您的应用程序试图调用先前版本的 class 上的方法时,该方法在较新版本的 class 上不可用。基本上,这可能是 upgrdading/downgrading 或移动到新环境时的版本冲突引起的。

https://docs.oracle.com/javase/9/docs/api/java/lang/NoSuchMethodError.html

这里有深入的描述。

检查应用程序库与服务器提供的库不会在这里使用。重要的是 JVM classloader 在运行时加载了什么 libs/classes。

通过java.class.path 系统属性 https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html

分析加载的内容class
System.getProperty("java.class.path");

然后将它们与您的 tomcat 版本提供的 jar 进行比较。