解决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中打开这个报错的类:

171126_KhCm_1434710.png

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

?
1
class  ClassMetadataReadingVisitor  extends  ClassVisitor  implements  ClassMetadata

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

171701_7Zs7_1434710.png

可以看到,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。


目录
相关文章
|
8月前
|
XML Java 数据库连接
【问题已解决】Caused by: java.lang.IllegalStateException
【问题已解决】Caused by: java.lang.IllegalStateException
105 0
|
4月前
|
Java
【Java报错】java.lang.ClassCastException: xxxClass cannot be cast to java.lang.Comparable 问题重现+解决
【Java报错】java.lang.ClassCastException: xxxClass cannot be cast to java.lang.Comparable 问题重现+解决
40 0
|
5月前
|
Java 数据库连接 数据库
解决Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
解决Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
|
11月前
|
XML Java 数据库连接
Mybatis提示Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lan
Mybatis提示Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lan
164 0
|
Java 应用服务中间件 Maven
nested exception is java.lang.IncompatibleClassChangeError: Implementing class(已解决)
nested exception is java.lang.IncompatibleClassChangeError: Implementing class(已解决)
280 0
nested exception is java.lang.IncompatibleClassChangeError: Implementing class(已解决)
|
Java
Caused by: java.lang.NoSuchFieldError: REFLECTION
Caused by: java.lang.NoSuchFieldError: REFLECTION
506 0
Caused by: java.lang.NoSuchFieldError: REFLECTION
|
Java 测试技术
Cannot instantiate test(s): java.lang.SecurityException: Prohibited package name: java
Cannot instantiate test(s): java.lang.SecurityException: Prohibited package name: java
Cannot instantiate test(s): java.lang.SecurityException: Prohibited package name: java
|
Java
Java - java.lang.IllegalStateException: No modifications are allowed to a locked ParameterMap
Java - java.lang.IllegalStateException: No modifications are allowed to a locked ParameterMap
393 0
|
Java Spring
【JUnit 报错】java.lang.IncompatibleClassChangeError
使用Junit 测试spring时候报错: 1 java.lang.IncompatibleClassChangeError: class org.springframework.core.LocalVariableTableParameterNameDiscoverer$ParameterNameDiscoveringVisitor has interface org.
1248 0
|
Java 数据库连接 Spring
java.lang.reflect.MalformedParameterizedTypeException 的解决办法
近期在开发项目时用到了spring mvc 和mybatis时运行出现如下错误: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [config/spring-d
5157 0