什么原因导致java.lang.CompatibleClassChangeError?
我将Java库打包为一个JAR,当我试图从它调用方法时,它抛出了许多什么原因导致java.lang.CompatibleClassChangeError?,java,jar,runtime-error,binary-compatibility,Java,Jar,Runtime Error,Binary Compatibility,我将Java库打包为一个JAR,当我试图从它调用方法时,它抛出了许多Java.lang.CompatibleClassChangeErrors。这些错误似乎是随机出现的。什么样的问题可能会导致此错误?这意味着您在没有重新编译客户端代码的情况下对库进行了一些不兼容的二进制更改。详细说明所有此类更改,最突出的是将非静态非私有字段/方法更改为静态,反之亦然 根据新库重新编译客户机代码,您应该可以开始了 更新:如果发布公共库,应尽可能避免进行不兼容的二进制更改,以保持所谓的“二进制向后兼容性”。理想情况
Java.lang.CompatibleClassChangeError
s。这些错误似乎是随机出现的。什么样的问题可能会导致此错误?这意味着您在没有重新编译客户端代码的情况下对库进行了一些不兼容的二进制更改。详细说明所有此类更改,最突出的是将非静态
非私有字段/方法更改为静态
,反之亦然
根据新库重新编译客户机代码,您应该可以开始了
更新:如果发布公共库,应尽可能避免进行不兼容的二进制更改,以保持所谓的“二进制向后兼容性”。理想情况下,单独更新依赖项jar不会破坏应用程序或构建。如果您必须中断二进制向后兼容性,则在发布更改之前必须增加主要版本号(例如,从1.x.y增加到2.0.0)。这意味着您在不重新编译客户端代码的情况下对库进行了一些不兼容的二进制更改。详细说明所有此类更改,最突出的是将非
静态
非私有字段/方法更改为静态
,反之亦然
根据新库重新编译客户机代码,您应该可以开始了
更新:如果发布公共库,应尽可能避免进行不兼容的二进制更改,以保持所谓的“二进制向后兼容性”。理想情况下,单独更新依赖项jar不会破坏应用程序或构建。如果您必须中断二进制向后兼容,则在发布更改之前必须增加主要版本号(例如从1.x.y增加到2.0.0)。您新打包的库与旧版本不向后二进制兼容。因此,一些未重新编译的库客户端可能会引发异常 这是Java库API中更改的完整列表,这些更改可能会导致使用旧版本库构建的客户端抛出Java.lang.不兼容ClassChangeError,如果它们在新版本上运行(即破坏BC):
japi-compliance-checker OLD.jar NEW.jar
clirr工具的使用:
java -jar clirr-core-0.6-uber.jar -o OLD.jar -n NEW.jar
祝你好运 新打包的库与旧版本不向后二进制兼容。因此,一些未重新编译的库客户端可能会引发异常 这是Java库API中更改的完整列表,这些更改可能会导致使用旧版本库构建的客户端抛出Java.lang.不兼容ClassChangeError,如果它们在新版本上运行(即破坏BC):
japi-compliance-checker OLD.jar NEW.jar
clirr工具的使用:
java -jar clirr-core-0.6-uber.jar -o OLD.jar -n NEW.jar
祝你好运>我也发现,当使用JNI时,从C++调用java方法,如果将参数以错误的顺序传递给调用java方法,则当尝试使用调用方法中的参数时,会得到此错误(因为它们不是正确的类型)。我最初感到惊讶的是,当您调用该方法时,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.
}
我也发现,当使用JNI时,从C++调用java方法,如果将参数以错误的顺序传递给调用java方法,则当尝试使用调用方法中的参数时,会得到此错误(因为它们不是正确的类型)。我最初感到惊讶的是,当您调用该方法时,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.
}
虽然这些答案都是正确的,但解决问题往往更容易
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
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;
}