How to fix java.lang.IncompatibleClassChangeError: Implementing class with cxf
How to fix java.lang.IncompatibleClassChangeError: Implementing class with cxf
我们在 RedHat linux 环境 运行 openjdk 版本“1.8.0_201”中对 tomcat 8 进行 SOAP 客户端调用时遇到问题,而相同的调用在 Windows 机器(tomcat 8,Oracle java 8)和 AIX(Oracle java 8,tomcat 7)上使用类似的配置工作正常.
这是堆栈跟踪:
java.lang.IncompatibleClassChangeError: Implementing class
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2401)
at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:859)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1333)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1185)
at org.apache.cxf.ws.addressing.impl.AddressingFeatureApplier.initializeProvider(AddressingFeatureApplier.java:36)
at org.apache.cxf.ws.addressing.WSAddressingFeature.initializeProvider(WSAddressingFeature.java:46)
at org.apache.cxf.feature.AbstractFeature.initialize(AbstractFeature.java:49)
at org.apache.cxf.frontend.ClientFactoryBean.applyFeatures(ClientFactoryBean.java:112)
at org.apache.cxf.frontend.ClientFactoryBean.create(ClientFactoryBean.java:100)
at org.apache.cxf.frontend.ClientProxyFactoryBean.create(ClientProxyFactoryBean.java:157)
at org.apache.cxf.jaxws.JaxWsProxyFactoryBean.create(JaxWsProxyFactoryBean.java:142)
at org.apache.cxf.jaxws.ServiceImpl.createPort(ServiceImpl.java:476)
at org.apache.cxf.jaxws.ServiceImpl.getPort(ServiceImpl.java:343)
at javax.xml.ws.Service.getPort(Service.java:160)
正在使用
cxf 版本 2.7.18
pom.xml 片段
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>3.0.16</version>
</dependency>
发生 IncompatibleClassChangeError
是因为某些代码是针对 API 的一个版本编译的,但在运行时正在加载 API 的不兼容版本。
(在这种情况下,"Implementing class" 不兼容意味着 class 已声明为 implements Something
,但在运行时 Something
结果是 class 而不是接口。不允许进行此 API 更改。)
问题是您包含的堆栈跟踪没有告诉我们 class 不兼容发生在什么地方,以及它与什么不兼容。唯一真正的线索是 CXF 似乎正在加载 "provider"
那么解决方法是什么?
没有灵丹妙药。您将需要进行一些挖掘以找出实际问题所在:
- 检查您从中获取堆栈跟踪的日志,以获取可能告诉您正在加载的内容的其他日志消息。
- 检查运行平台上各种CXF JAR文件的版本。
- 检查您在 webapp 本身和 Tomcat 的共享库目录中没有不同版本的 JAR。
- 修改 Tomcat 日志记录配置,将
org.apache.catalina.loader
包的日志记录级别设置为 DEBUG
。这将记录每个 class 从中加载的 JAR 文件。
由于导入不同版本的库和用于生成 WSDL 存根的插件,我正在获取 java.lang.IncompatibleClassChangeError
这些依赖项导致我的应用程序在启动时崩溃
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.4.3</version>
</dependency>
修改所用插件的版本(在依赖项和插件声明中),应用程序启动无误,Web 服务已正确部署并可以处理请求。
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.3.0</version>
</dependency>
我们在 RedHat linux 环境 运行 openjdk 版本“1.8.0_201”中对 tomcat 8 进行 SOAP 客户端调用时遇到问题,而相同的调用在 Windows 机器(tomcat 8,Oracle java 8)和 AIX(Oracle java 8,tomcat 7)上使用类似的配置工作正常.
这是堆栈跟踪:
java.lang.IncompatibleClassChangeError: Implementing class
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2401)
at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:859)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1333)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1185)
at org.apache.cxf.ws.addressing.impl.AddressingFeatureApplier.initializeProvider(AddressingFeatureApplier.java:36)
at org.apache.cxf.ws.addressing.WSAddressingFeature.initializeProvider(WSAddressingFeature.java:46)
at org.apache.cxf.feature.AbstractFeature.initialize(AbstractFeature.java:49)
at org.apache.cxf.frontend.ClientFactoryBean.applyFeatures(ClientFactoryBean.java:112)
at org.apache.cxf.frontend.ClientFactoryBean.create(ClientFactoryBean.java:100)
at org.apache.cxf.frontend.ClientProxyFactoryBean.create(ClientProxyFactoryBean.java:157)
at org.apache.cxf.jaxws.JaxWsProxyFactoryBean.create(JaxWsProxyFactoryBean.java:142)
at org.apache.cxf.jaxws.ServiceImpl.createPort(ServiceImpl.java:476)
at org.apache.cxf.jaxws.ServiceImpl.getPort(ServiceImpl.java:343)
at javax.xml.ws.Service.getPort(Service.java:160)
正在使用 cxf 版本 2.7.18
pom.xml 片段
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>3.0.16</version>
</dependency>
发生 IncompatibleClassChangeError
是因为某些代码是针对 API 的一个版本编译的,但在运行时正在加载 API 的不兼容版本。
(在这种情况下,"Implementing class" 不兼容意味着 class 已声明为 implements Something
,但在运行时 Something
结果是 class 而不是接口。不允许进行此 API 更改。)
问题是您包含的堆栈跟踪没有告诉我们 class 不兼容发生在什么地方,以及它与什么不兼容。唯一真正的线索是 CXF 似乎正在加载 "provider"
那么解决方法是什么?
没有灵丹妙药。您将需要进行一些挖掘以找出实际问题所在:
- 检查您从中获取堆栈跟踪的日志,以获取可能告诉您正在加载的内容的其他日志消息。
- 检查运行平台上各种CXF JAR文件的版本。
- 检查您在 webapp 本身和 Tomcat 的共享库目录中没有不同版本的 JAR。
- 修改 Tomcat 日志记录配置,将
org.apache.catalina.loader
包的日志记录级别设置为DEBUG
。这将记录每个 class 从中加载的 JAR 文件。
由于导入不同版本的库和用于生成 WSDL 存根的插件,我正在获取 java.lang.IncompatibleClassChangeError
这些依赖项导致我的应用程序在启动时崩溃
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.4.3</version>
</dependency>
修改所用插件的版本(在依赖项和插件声明中),应用程序启动无误,Web 服务已正确部署并可以处理请求。
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>3.3.0</version>
</dependency>