[How to Solve] java.lang.IncompatibleClassChangeError

 

Today, after sorting out the pom.xml file of maven, we integrated multiple projects with Maven. As a result, when we started tomcat, we encountered a wonderful error:
when we started Tomcat

Warning: Servlet[spring]inwebapplication[/AbcWeb]threwload()exception
java.lang.IncompatibleClassChangeError:classorg.springframework.core.type.classreading.ClassMetadataReadingVisitorhasinterfaceorg.springframework.asm.ClassVisitorassuperclass
	atjava.lang.ClassLoader.defineClass1(NativeMethod)
	atjava.lang.ClassLoader.defineClass(ClassLoader.java:800)
	atjava.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	atorg.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2495)
	atorg.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:859)
	atorg.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1301)
	atorg.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1166)
	atjava.lang.ClassLoader.defineClass1(NativeMethod)

Restart Tomcat, Project>Clean are played all over, but did not find where the problem is. So Google it, the results from this page found this paragraph:

Your newly packaged libraryis 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 acompletelist of changes in Java library API that may cause clients built with an old version of the library to throw java.lang.IncompatibleClassChangeErrorif they run on a new one (i.e. breaking BC):

Non-final field become static,

Non-constant field become non-static,

Class become interface,

Interface become class,

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).

In fact, a closer look reveals that the error description is actually quite clear:

java.lang.IncompatibleClassChangeError:classorg.springframework.core.type.classreading.ClassMetadataReadingVisitorhasinterfaceorg.springframework.asm.ClassVisitorassuperclass

That is to say, has a class called classmetadatareadingvisitor, which takes an interface called classvisitor as its parent class . But we all know that the relationship between class and interface in java can only be realized, not inherited . So why is this class?I try to open this error reporting class in Eclipse:

As you can see, two versions of classmetadatareadingvisitor classes (3.2.6 and 4.0.0) can be found in my workspace. Open these two classes respectively (Maven will download the source code automatically). You can see that the class declaration is:

classClassMetadataReadingVisitorextendsClassVisitorimplementsClassMetadata

So I opened the classvisitor class mentioned in the error description, and the result is as follows:

As you can see, eclipse found three such classes in workspace, and the package name and class name are all exactly the same. As you can see, in version 3.1.4 of spring, this class called classvisitor is actually an interface, which is placed in the spring ASM module. In versions 3.2.6 and 4.0.0, the classvisitor becomes an abstract class

After finding this difference, I checked the version of my spring core module:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.6</version>
</dependency>

But at the same time, there is a dependency of such a package in my pom.xml

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-asm</artifactId>
<version>3.1.4.RELEASE</version>
</dependency>

It happens that the 3.1.4 interface is in workspace, so the classvisitor is included in both packages. After deleting the spring ASM module, the error disappears and the problem is solved

The spring ASM package doesn’t know when it was imported, which tells us:

when using Maven to process dependent packages, you must not arbitrarily add dependencies. Only used packages are imported, and statements that do not use packages should be deleted in time

when integrating multiple Maven projects, you should pay attention to the version of the dependency package, because some classes (fields that may be included in the package) may have different declarations in different versions, and wrong class or field declarations will lead to incompatible classchangeerror

 

Similar Posts: