我将一个Java库打包为JAR,当我试图从它调用方法时,它抛出许多Java .lang. incompatibleclasschangeerror。这些错误似乎是随机出现的。什么样的问题会导致这个错误?


当前回答

请检查你的代码是否由两个具有相同类名和包定义的模块项目组成。例如,如果有人使用复制粘贴来创建基于先前实现的接口的新实现,就会发生这种情况。

其他回答

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

如果这种行为看起来是随机的,那么它很可能是多线程程序类根据最先遇到的代码加载不同的传递依赖项的结果。

要解决这些问题,请尝试使用-verbose作为参数启动VM,然后查看异常发生时正在加载的类。你应该会看到一些令人惊讶的信息。例如,拥有相同依赖项的多个副本,以及您从未预料到的版本,或者如果您知道它们被包括在内,您就不会接受这些版本。

用Maven解决重复的jar最好是结合Maven下的Maven - Dependency - Plugin和Maven -enforcer- Plugin(或SBT的Dependency Graph Plugin),然后将这些jar添加到顶级POM的一部分或作为SBT中的导入依赖元素(以删除这些依赖)。

好运!

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.

高级:如果A必须使用C的v1, B必须使用C的v2,那么我们必须在A和B的poms中重新定位C,以避免类冲突(我们有一个重复类警告),当构建依赖于A和B的最终项目时。

我得到这个错误是因为我有一个抽象基类,它承诺实现某个接口,但我忘记了添加接口方法的实现,然后我创建了一个非抽象(具体)字节码生成的类,它扩展了抽象类,也没有提供这些方法的实现。

当我尝试创建字节码生成类的实例时,JVM抱怨java.lang.IncompatibleClassChangeError。

幸运的是,该异常有一个“message”成员,它提供了关于出错原因的更详细信息。在我的例子中,消息清楚地说,特定的类应该实现特定的接口,但它实际上并没有实现它。

我的答案,我相信,将是Intellij具体。

我重新构建干净,甚至手动删除“out”和“target”dirs。Intellij有一个“无效缓存并重新启动”,它有时会清除奇怪的错误。这次没有成功。依赖版本在项目设置->模块菜单中看起来都是正确的。

最后的答案是从本地maven repo中手动删除我的问题依赖项。旧版本的bouncycastle是罪魁祸首(我知道我只是改变了版本,这就是问题所在),尽管旧版本没有出现在正在建造的东西中,但它解决了我的问题。我使用的是intellij版本14,然后在此过程中升级到15。

由于某种原因,当使用JNI并在调用Call*Method()时传递jclass参数而不是jobject时,也会抛出相同的异常。

这与《食人魔诗篇》第33篇中的回答相似。

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;
}

我知道在被问到这个问题5年后再回答这个问题有点晚了,但这是搜索java.lang.IncompatibleClassChangeError时最热门的问题之一,所以我想记录这个特殊情况。