解决java.lang.IncompatibleClassChangeError

今天整理了Maven的pom.xml文件后,把多个项目用maven集成在了一起,结果在启动Tomcat的时候,遇到一个奇葩的错误:

?


1

2

3

4

5

6

7

8

9

10

严重: Servlet [spring] in web application [/AbcWeb] threw load() exception

java.lang.IncompatibleClassChangeError: class org.springframework.core.type.classreading.ClassMetadataReadingVisitor has interface org.springframework.asm.ClassVisitor as super class

    at java.lang.ClassLoader.defineClass1(Native Method)

    at java.lang.ClassLoader.defineClass(ClassLoader.java:800)

    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)

    at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2495)

    at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:859)

    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1301)

    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1166)

    at java.lang.ClassLoader.defineClass1(Native Method)

重启Tomcat,Project>Clean都玩遍了,也没找到问题在哪里。。。于是Google之,结果从这个页面里找到了这样一段话:

Your newly packaged library is not backward binary compatible (BC) with old version. For this reason some of the library clients that are not recompiled may throw the exception.

This is a complete list of changes in Java library API that may cause clients built with an old version of the library to throw java.lang.IncompatibleClassChangeError if they run on a new one (i.e. breaking BC):

  1. Non-final field become static,
  2. Non-constant field become non-static,
  3. Class become interface,
  4. Interface become class,
  5. if you add a new field to class/interface (or add new super-class/super-interface) then a static field from a super-interface of a client class C may hide an added field (with the same name) inherited from the super-class of C (very rare case).

其实,细心一点可以发现,错误描述其实很清晰了:

?


1

java.lang.IncompatibleClassChangeError: class org.springframework.core.type.classreading.ClassMetadataReadingVisitor has interface org.springframework.asm.ClassVisitor as super class

意思是说,有个叫ClassMetadataReadingVisitor的类,以一个叫ClassVisitor的接口作为父类了。但是大家都知道,Java中类和接口的关系只能是实现,而不是继承。那么为什么会出现这个类呢?我尝试着在Eclipse中打开这个报错的类:

可以看到,我的Workspace中可以发现两个版本(3.2.6和4.0.0)的ClassMetadataReadingVisitor类,分别打开这两个类(Maven会自动下载源代码),可以看到类的声明均为:

?


1

class ClassMetadataReadingVisitor extends ClassVisitor implements ClassMetadata

于是我又打开错误描述中提到的ClassVisitor这个类,结果却是这样的:

可以看到,Eclipse在Workspace中发现了3个这样的类,而且包名类名都完全一样。可以看到,在spring的3.1.4版本中,这个叫ClassVisitor的类其实是一个接口,这个接口被放在spring-asm模块中。而在3.2.6和4.0.0版本中,这个ClassVisitor就变成了一个抽象类。

发现这个差别后,我检查了我的spring-core模块的版本:

?


1

2

3

4

5

<dependency>

    <groupId>org.springframework</groupId>

    <artifactId>spring-core</artifactId>

    <version>3.2.6</version>

</dependency>

但同时我的pom.xml中还有这样一个包的依赖:

?


1

2

3

4

5

<dependency>

    <groupId>org.springframework</groupId>

    <artifactId>spring-asm</artifactId>

    <version>3.1.4.RELEASE</version>

</dependency>

正好这个3.1.4的接口就在Workspace中,于是这两个包当中都有这个ClassVisitor,删掉spring-asm模块后,错误消失,问题解决。

这个spring-asm包也不知道什么时候导入的,这就告诉我们:

  1. 在使用Maven处理依赖包的时候,一定不要随便乱添加依赖,用到的包才导入,没用到包的声明要及时删掉。
  2. 在整合多个maven项目的时候,要注意依赖包的版本,因为有些类(可能包含有的字段)在不同的版本中声明可能会不同,错误的类或字段声明将导致IncompatibleClassChangeError。
时间: 2024-12-01 05:16:55

解决java.lang.IncompatibleClassChangeError的相关文章

SRVE0068E: 未捕获到 servlet CXFServlet 的其中一个服务方法中抛出的异常。抛出的异常:java.lang.IncompatibleClassChangeError

问题描述 RT.[08-10-2516:37:40:421CST]00000030ServletWrappeESRVE0068E:未捕获到servletCXFServlet的其中一个服务方法中抛出的异常.抛出的异常:java.lang.IncompatibleClassChangeErroratorg.apache.cxf.wsdl11.ServiceWSDLBuilder.addExtensibiltyElements(ServiceWSDLBuilder.java:227)atorg.apa

解决java.lang.NoClassDefFoundError: org.jdom.Content

报错:java.lang.NoClassDefFoundError: org.jdom.Content 解决办法: 更新lib目录下的jdom.jar 至最新版本.

【eclipse】 怎么解决java.lang.NoClassDefFoundError错误

前言 在日常Java开 发中,我们经常碰到java.lang.NoClassDefFoundError这样的错误,需要花费很多时间去找错误的原因,具体是哪个类不见了?类 明明还在,为什么找不到?而且我们很容易把java.lang.NoClassDefFoundError和 java.lang.ClassNotfoundException这两个错误搞混,事实上这两个错误是完全不同的.我们往往花费时间去不断尝试一些其他 的方法去解决这个问题,而没有真正去理解这个错误的原因.这篇文章就是通过解决NoC

求解决java.lang.IllegalArgumentException: id to load is required for loading

问题描述 java.lang.IllegalArgumentException:idtoloadisrequiredforloadingorg.hibernate.event.LoadEvent.<init>(LoadEvent.java:89)org.hibernate.event.LoadEvent.<init>(LoadEvent.java:61)org.hibernate.impl.SessionImpl.get(SessionImpl.java:994)org.hiber

servlet action 的某一服务方法创建了未捕获到的异常 java.lang.IncompatibleClassChangeError

问题描述 RT[14-9-2814:14:02:578CST]00000024servletEcom.ibm.ws.webcontainer.servlet.ServletWrapperserviceSRVE0068E:应用程序xTransSvc中servletaction的某一服务方法创建了未捕获到的异常.创建的异常:java.lang.IncompatibleClassChangeErroratcom.hiaward.xtranssvc.service.Trans_0100_00000_04

java.lang.NoClassDefFoundError 问题求解答

问题描述 java.lang.NoClassDefFoundError 问题求解答 自己做的小程序,引用百度地图的时候 出现的异常,我另外有个项目是导入的项目,里面也是有百度的SDK引用,同样的eclipse和ADT的版本,没有出现这个异常,试了网上的很多办法,没有能解决.求大神指教! 解决方案 [问题]java.lang.NoClassDefFoundError如何解决java.lang.NoClassDefFoundError问题解决 java.lang.NoClassDefFoundErr

Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结(转)

java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生该错误的原因大都出于以下原因:JVM内存过小.程序不严密,产生了过多的垃圾. 导致OutOfMemoryError异常的常见原因有以下几种: 内存中加载的数据量过于庞大,如一次从数据库取出过多数据: 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收: 代码中存在死循环或循环产生过多重复的对象实体: 使用的第三方软件中的BUG: 启动参数内存值设定的过小: 此错误常见的错误提示: tomcat

java.lang.OutOfMemoryError: unable to create new native thread(转)

解决 - java.lang.OutOfMemoryError: unable to create new native thread 工作中碰到过这个问题好几次了,觉得有必要总结一下,所以有了这篇文章,这篇文章分为三个部分:认识问题.分析问题.解决问题.  一.认识问题:  首先我们通过下面这个 测试程序 来认识这个问题: 运行的环境 (有必要说明一下,不同环境会有不同的结果):32位 Windows XP, 1.5.0_22, myeclipse 6.6, 测试程序:  Java代码  im

如何解决 java 插入 mysql longblob 出现 OutOfMemery

问题描述 插入一个几十M(测试的文件是80M)文件就出现OOMJDBC和Hibernate都试过了请问这个问题如何解决java.lang.OutOfMemoryError: Java heap spaceat com.mysql.jdbc.Buffer.ensureCapacity(Buffer.java:155)at com.mysql.jdbc.PreparedStatement.fillSendPacket(PreparedStatement.java:2164)at com.mysql.