I'm packaging a Java library as a JAR, and it's throwing many java.lang.IncompatibleClassChangeError
s when I try to invoke methods from it. These errors seem to appear at random. What kinds of problems could be causing this error?
-
In an Eclipse project where I was testing Apache FOP 1.0 and Barcode4J, the additional libraries that came with Barcode4J were apparently overriding the ones that came with FOP (some had higher version numbers). It's a case for being very careful what you put in your build path / classpath. – Wivani Jun 15 '11 at 08:06
21 Answers
This means that you have made some incompatible binary changes to the library without recompiling the client code. Java Language Specification §13 details all such changes, most prominently, changing non-static
non-private fields/methods to be static
or vice versa.
Recompile the client code against the new library, and you should be good to go.
UPDATE: If you publish a public library, you should avoid making incompatible binary changes as much as possible to preserve what's known as "binary backward compatibility". Updating dependency jars alone ideally shouldn't break the application or the build. If you do have to break binary backward compatibility, it's recommended to increase the major version number (e.g. from 1.x.y to 2.0.0) before releasing the change.

- 303
- 4
- 14

- 58,763
- 21
- 123
- 144
-
3For some reason the developers here are having a problem where recompiling the client code doesn't fix the issue exactly. For some reason if they edit the file where it occurs and recompile the error no longer occurs there, but more will randomly pop-up elsewhere in the project, where the library is referenced. I am curious what could possibly be casuing this. – Zombies Dec 30 '09 at 15:42
-
6Have you tried to do a clean build (delete all the `*.class` files) and recompiling? Editing files have similar effect. – notnoop Dec 30 '09 at 15:52
-
No dynamically generated code.... unless you would consider a JSP to be such. We did try deleting the class files and this didn't seem to help. The wierd thing is that it just doesn't seem to happen for me but it happens for other developer. – Zombies Dec 30 '09 at 16:54
-
2Can you ensure that when you do a clean build you are compiling against the same jars you run with? – notnoop Dec 30 '09 at 19:18
-
Is there something concerned with 32bit or 64bit platform , I found a error only perform in 64bit platform. – cowboi-peng Sep 26 '17 at 03:21
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):
- 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).
Note: There are many other exceptions caused by other incompatible changes: NoSuchFieldError, NoSuchMethodError, IllegalAccessError, InstantiationError, VerifyError, NoClassDefFoundError and AbstractMethodError.
The better paper about BC is "Evolving Java-based APIs 2: Achieving API Binary Compatibility" written by Jim des Rivières.
There are also some automatic tools to detect such changes:
Usage of japi-compliance-checker for your library:
japi-compliance-checker OLD.jar NEW.jar
Usage of clirr tool:
java -jar clirr-core-0.6-uber.jar -o OLD.jar -n NEW.jar
Good luck!

- 15,843
- 6
- 60
- 87
While these answers are all correct, resolving the problem is often more difficult. It's generally the result of two mildly different versions of the same dependency on the classpath, and is almost always caused by either a different superclass than was originally compiled against being on the classpath or some import of the transitive closure being different, but generally at class instantiation and constructor invocation. (After successful class loading and ctor invocation, you'll get NoSuchMethodException
or whatnot.)
If the behavior appears random, it's likely the result of a multithreaded program classloading different transitive dependencies based on what code got hit first.
To resolve these, try launching the VM with -verbose
as an argument, then look at the classes that were being loaded when the exception occurs. You should see some surprising information. For instance, having multiple copies of the same dependency and versions you never expected or would have accepted if you knew they were being included.
Resolving duplicate jars with Maven is best done with a combination of the maven-dependency-plugin and maven-enforcer-plugin under Maven (or SBT's Dependency Graph Plugin, then adding those jars to a section of your top-level POM or as imported dependency elements in SBT (to remove those dependencies).
Good luck!

- 3,235
- 28
- 33
-
7The verbose argument helped me pinpoint which jars were giving problems. Thanks – Virat Kadaru Jul 19 '13 at 23:11
-
1As an alternative to the quite overwhelming -verbose output, you may be able to use the 'Depedency analyzer' in your IDE (IntelliJ IDEA in my case). Filter for warnings and read what dependencies are being warned about. – GerardV Aug 20 '23 at 12:16
I have also discovered that, when using JNI, invoking a Java method from C++, if you pass parameters to the invoked Java method in the wrong order, you will get this error when you attempt to use the parameters inside the called method (because they won't be the right type). I was initially taken aback that JNI does not do this checking for you as part of the class signature checking when you invoke the method, but I assume they don't do this kind of checking because you may be passing polymorphic parameters and they have to assume you know what you are doing.
Example C++ JNI Code:
void invokeFooDoSomething() {
jobject javaFred = FredFactory::getFred(); // Get a Fred jobject
jobject javaFoo = FooFactory::getFoo(); // Get a Foo jobject
jobject javaBar = FooFactory::getBar(); // Get a Bar jobject
jmethodID methodID = getDoSomethingMethodId() // Get the JNI Method ID
jniEnv->CallVoidMethod(javaFoo,
methodID,
javaFred, // Woops! I switched the Fred and Bar parameters!
javaBar);
// << Insert error handling code here to discover the JNI Exception >>
// ... This is where the IncompatibleClassChangeError will show up.
}
Example Java Code:
class Bar { ... }
class Fred {
public int size() { ... }
}
class Foo {
public void doSomething(Fred aFred, Bar anotherObject) {
if (name.size() > 0) { // Will throw a cryptic java.lang.IncompatibleClassChangeError
// Do some stuff...
}
}
}

- 21,366
- 16
- 74
- 92
-
1Thanks for the hint. I had the same problem when calling a Java method with the wrong instance (this) supplied. – sstn Sep 19 '14 at 14:18
I had the same issue, and later I figured out that I am running the application on Java version 1.4 while the application is compiled on version 6.
Actually, the reason was of having a duplicate library, one is located within the classpath and the other one is included inside a jar file that is located within the classpath.

- 115,165
- 71
- 313
- 417
-
How did you get to the bottom of this? Im sure I have a similar problem but dont have a clue how to trace which dependency library is being duplicated. – beterthanlife May 08 '13 at 10:21
-
@beterthanlife write a script that searches inside all the jar files looking for duplicated classes (search by their full-qualified name, i.e with package name) :) – Eng.Fouad May 08 '13 at 10:30
-
ok, using NetBeans and maven-shade I think I can see all of the classes which are being duplicated and the jar files they reside in. Many of these jar files I dont have directly referenced in my pom.xml, so I assume they must be being included by my dependencies. Is there an easy way to find out which dependency is including them, without going through each of the dependencies' pom file? (please pardon my noobishness, Im a java virgin!) – beterthanlife May 08 '13 at 10:41
-
-
I found a duplicate jar by looking at the gradle dependencies graph (./gradlew :
:dependencies). So I found the culprit that drew the old version of the lib into the project. – nyx Apr 22 '15 at 14:42
In my case, I ran into this error this way. pom.xml
of my project defined two dependencies A
and B
. And both A
and B
defined dependency on same artifact (call it C
) but different versions of it (C.1
and C.2
). When this happens, for each class in C
maven can only select one version of the class from the two versions (while building an uber-jar). It will select the "nearest" version based on its dependency mediation rules and will output a warning "We have a duplicate class..." If a method/class signature changes between the versions, it can cause a java.lang.IncompatibleClassChangeError
exception if the incorrect version is used at runtime.
Advanced: If A
must use v1 of C
and B
must use v2 of C
, then we must relocate C
in A
and B
's poms to avoid class conflict (we have a duplicate class warning) when building the final project that depends on both A
and B
.
In my case the error appeared when I added the com.nimbusds
library in my application deployed on Websphere 8.5
.
The below exception occurred:
Caused by: java.lang.IncompatibleClassChangeError: org.objectweb.asm.AnnotationVisitor
The solution was to exclude the asm jar from the library:
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>5.1</version>
<exclusions>
<exclusion>
<artifactId>asm</artifactId>
<groupId>org.ow2.asm</groupId>
</exclusion>
</exclusions>
</dependency>

- 709
- 7
- 18

- 29
- 5
All of the above - for whatever reason I was doing some big refactor and starting to get this. I renamed the package my interface was in and that cleared it. Hope that helps.

- 4,479
- 1
- 36
- 50
I have a web application that deploys perfectly fine on my local machine's tomcat(8.0.20). However, when I put it into the qa environment (tomcat - 8.0.20), it kept on giving me the IncompatibleClassChangeError and it was complaining that I was extending on an interface. This interface was changed to an abstract class. And I compiled the parent and child classes and still I kept on getting the same issue. Finally, I wanted to debug, so, I changed the version on the parent to x.0.1-SNAPSHOT and then compiled everything and now it is working. If someone is still hitting the problem after following the answers given here, please make sure the versions in your pom.xml are also correct. Change the versions to see if that works. If so, then fix the version problem.

- 111
- 1
- 8
My answer, I believe, will be Intellij specific.
I had rebuilt clean, even going as far as to manually delete the "out" and "target" dirs. Intellij has a "invalidate caches and restart", which sometimes clears odd errors. This time it didn't work. The dependency versions all looked correct in the project settings->modules menu.
The final answer was to manually delete my problem dependency from my local maven repo. An old version of bouncycastle was the culprit(I knew I had just changed versions and that would be the problem) and although the old version showed up no where in what was being built, it solved my problem. I was using intellij version 14 and then upgraded to 15 during this process.

- 144
- 1
- 5
An additional cause of this issue, is if you have Instant Run
enabled for Android Studio.
The fix
If you find you start getting this error, turn off Instant Run
.
- Android Studio main settings
- Build, Execution, Deployment
- Instant Run
- Untick "Enable instant run..."
Why
Instant Run
modifies a large number of things during development, to make it quicker to provide updates to your running App. Hence instant run. When it works, it is really useful. However, when an issue such as this strikes, the best thing to do is to turn off Instant Run
until the next version of Android Studio releases.

- 15,802
- 10
- 54
- 91
Another situation where this error can appear is with Emma Code Coverage.
This happens when assigning an Object to an interface. I guess this has something to do with the Object being instrumented and not binary compatible anymore.
http://sourceforge.net/tracker/?func=detail&aid=3178921&group_id=177969&atid=883351
Fortunately this problem doesn't happen with Cobertura, so I've added cobertura-maven-plugin in my reporting plugins of my pom.xml

- 83,644
- 31
- 142
- 199
I've faced this issue while undeploying and redeploying a war with glassfish. My class structure was like this,
public interface A{
}
public class AImpl implements A{
}
and it was changed to
public abstract class A{
}
public class AImpl extends A{
}
After stopping and restarting the domain, it worked out fine. I was using glassfish 3.1.43

- 14,532
- 10
- 61
- 73
Please check if your code doesnt consist of two module projects that have the same classes names and packages definition. For example this could happen if someone uses copy-paste to create new implementation of interface based on previous implementation.

- 2,170
- 2
- 23
- 28
If this is a record of possible occurences of this error then:
I just got this error on WAS (8.5.0.1), during the CXF (2.6.0) loading of the spring (3.1.1_release) configuration where a BeanInstantiationException rolled up a CXF ExtensionException, rolling up a IncompatibleClassChangeError. The following snippet shows the gist of the stack trace:
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.apache.cxf.bus.spring.SpringBus]: Constructor threw exception; nested exception is org.apache.cxf.bus.extension.ExtensionException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:162)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:76)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:990)
... 116 more
Caused by: org.apache.cxf.bus.extension.ExtensionException
at org.apache.cxf.bus.extension.Extension.tryClass(Extension.java:167)
at org.apache.cxf.bus.extension.Extension.getClassObject(Extension.java:179)
at org.apache.cxf.bus.extension.ExtensionManagerImpl.activateAllByType(ExtensionManagerImpl.java:138)
at org.apache.cxf.bus.extension.ExtensionManagerBus.<init>(ExtensionManagerBus.java:131)
[etc...]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
... 118 more
Caused by: java.lang.IncompatibleClassChangeError:
org.apache.neethi.AssertionBuilderFactory
at java.lang.ClassLoader.defineClassImpl(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:284)
[etc...]
at com.ibm.ws.classloader.CompoundClassLoader.loadClass(CompoundClassLoader.java:586)
at java.lang.ClassLoader.loadClass(ClassLoader.java:658)
at org.apache.cxf.bus.extension.Extension.tryClass(Extension.java:163)
... 128 more
In this case, the solution was to change the classpath order of the module in my war file. That is, open up the war application in the WAS console under and select the client module(s). In the module configuration, set the class-loading to be "parent last".
This is found in the WAS console:
- Applicatoins -> Application Types -> WebSphere Enterprise Applications
- Click link representing your application (war)
- Click "Manage Modules" under "Modules" section
- Click link for the underlying module(s)
- Change "Class loader order" to be "(parent last)".

- 5,995
- 2
- 27
- 40
Documenting another scenario after burning way too much time.
Make sure you don't have a dependency jar that has a class with an EJB annotation on it.
We had a common jar file that had an @local
annotation. That class was later moved out of that common project and into our main ejb jar project. Our ejb jar and our common jar are both bundled within an ear. The version of our common jar dependency was not updated. Thus 2 classes trying to be something with incompatible changes.

- 15,474
- 10
- 62
- 77
For some reason the same exception is also thrown when using JNI and passing the jclass argument instead of the jobject when calling a Call*Method()
.
This is similar to the answer from Ogre Psalm33.
void example(JNIEnv *env, jobject inJavaList) {
jclass class_List = env->FindClass("java/util/List");
jmethodID method_size = env->GetMethodID(class_List, "size", "()I");
long size = env->CallIntMethod(class_List, method_size); // should be passing 'inJavaList' instead of 'class_List'
std::cout << "LIST SIZE " << size << std::endl;
}
I know it is a bit late to answer this question 5 years after being asked but this is one of the top hits when searching for java.lang.IncompatibleClassChangeError
so I wanted to document this special case.

- 1,076
- 9
- 9
Adding my 2 cents .If you are using scala and sbt and scala-logging as dependency ;then this can happen because scala-logging's earlier version had the name scala-logging-api.So;essentially the dependency resolutions do not happen because of different names leading to runtime errors while launching the scala application.

- 466
- 4
- 13
I got this error because I had an abstract base class which promised that it implements a certain interface, but I had forgotten to add the implementations of the interface methods, and then I created a non-abstract (concrete) bytecode-generated class which extended the abstract class, without providing implementations for those methods, either.
When I tried to create an instance the bytecode-generated class, the JVM complained with java.lang.IncompatibleClassChangeError
.
Luckily, the exception has a "message" member which provides more detailed information as to what went wrong. In my case the message clearly said that the particular class was supposed to implement the particular interface, but it did not actually implement it.

- 56,297
- 11
- 110
- 142
If you came from android development. Then give a try of rebuild
option might be fix for you.

- 896
- 9
- 20
In my case:
- I have a project containing a few modules, including
app
,test
,integrationTest
- I created
OneElementCache
in app module. - Then, I created a file
Cache
in test module, the file contains some helpers for creatingOneElementCache
in tests. - Until now, everything works perfectly (both
test
andintegrationTest
passes). - After that, I created a file
Cache
in app module. - Got while running
integrationTest
:
Caused by: java.lang.IncompatibleClassChangeError:
class app.cache.CacheImpl can not implement app.cache.Cache, because it is not an interface (app.cache.Cache is in unnamed module of loader 'app')
The reason was a conflict in naming in different modules (app/test). Changing the filename in test did the job.

- 4,303
- 1
- 17
- 35