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


当前回答

另一种可能出现此错误的情况是Emma Code Coverage。

这发生在将Object分配给接口时。我猜这与对象被检测和不再二进制兼容有关。

http://sourceforge.net/tracker/?func=detail&aid=3178921&group_id=177969&atid=883351

幸运的是,这个问题在Cobertura中没有发生,所以我在pom.xml的报告插件中添加了Cobertura -maven-plugin

其他回答

在我的例子中,当我添加com时出现了错误。nimbusds库在我部署在Websphere 8.5的应用程序中。 发生了以下异常:

原因:java.lang.IncompatibleClassChangeError: org.objectweb.asm.AnnotationVisitor

解决方案是从库中排除asm jar:

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

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.

示例c++ JNI代码:

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

Java代码示例:

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

在浪费了太多时间后记录下另一个场景。

确保您的依赖jar中没有包含带有EJB注释的类。

我们有一个普通的jar文件,它有一个@local注释。这个类后来从这个公共项目移到我们的主ejb jar项目中。ejb jar和公共jar都捆绑在ear中。我们的公共jar依赖项的版本没有更新。因此,两个类试图成为具有不兼容的更改的东西。

我的答案,我相信,将是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时最热门的问题之一,所以我想记录这个特殊情况。