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


当前回答

这意味着您已经对库进行了一些不兼容的二进制更改,而无需重新编译客户端代码。Java语言规范§13详细描述了所有这些更改,最突出的是将非静态的非私有字段/方法更改为静态或反之亦然。

根据新的库重新编译客户端代码,应该就可以开始了。

更新:如果你发布了一个公共库,你应该尽可能避免做出不兼容的二进制更改,以保持所谓的“二进制向后兼容性”。单独更新依赖jar在理想情况下不会破坏应用程序或构建。如果你不得不打破二进制向后兼容性,建议增加主版本号(例如从1.x。Y到2.0.0),然后发布更改。

其他回答

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

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

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

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

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

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

在我的例子中,当我添加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>

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中的导入依赖元素(以删除这些依赖)。

好运!

这意味着您已经对库进行了一些不兼容的二进制更改,而无需重新编译客户端代码。Java语言规范§13详细描述了所有这些更改,最突出的是将非静态的非私有字段/方法更改为静态或反之亦然。

根据新的库重新编译客户端代码,应该就可以开始了。

更新:如果你发布了一个公共库,你应该尽可能避免做出不兼容的二进制更改,以保持所谓的“二进制向后兼容性”。单独更新依赖jar在理想情况下不会破坏应用程序或构建。如果你不得不打破二进制向后兼容性,建议增加主版本号(例如从1.x。Y到2.0.0),然后发布更改。