standard jre jdk for edition downloads developers java compiler-construction jar runtime-error binary-compatibility

java - jdk - jre 11 download



¿Qué causa java.lang.IncompatibleClassChangeError? (17)

Agregando mis 2 centavos. Si está usando scala y sbt y scala-logging como dependencia, entonces esto puede suceder porque la versión anterior de scala-logging tenía el nombre scala-logging-api.Entonces, esencialmente, las resoluciones de dependencia no ocurren debido a diferentes nombres que conducen a errores de tiempo de ejecución al iniciar la aplicación scala.

Estoy empaquetando una biblioteca de Java como un JAR, y estoy lanzando muchos java.lang.IncompatibleClassChangeError s cuando intento invocar métodos desde ella. Estos errores parecen aparecer al azar. ¿Qué tipo de problemas podrían estar causando este error?


Compruebe si su código no consta de dos proyectos de módulo que tengan los mismos nombres de clases y definición de paquetes. Por ejemplo, esto podría suceder si alguien utiliza copiar y pegar para crear una nueva implementación de la interfaz basada en la implementación anterior.


Documentar otro escenario después de quemar demasiado tiempo.

Asegúrese de no tener un jar de dependencia que tenga una clase con una anotación EJB en él.

Teníamos un archivo jar común que tenía una anotación @local . Esa clase se mudó luego de ese proyecto común a nuestro proyecto principal de ejb jar. Nuestro frasco de ejb y nuestro frasco común están empaquetados dentro de una oreja. La versión de nuestra dependencia de jar común no se actualizó. Así 2 clases intentando ser algo con cambios incompatibles.


En mi caso, me encontré con este error de esta manera. pom.xml de mi proyecto definió dos dependencias A y B Y tanto A como B definieron la dependencia de un mismo artefacto (llamémoslo C ) pero diferentes versiones de él ( C.1 y C.2 ). Cuando esto sucede, para cada clase en C maven solo puede seleccionar una versión de la clase de las dos versiones (mientras se construye un uber-jar ). Seleccionará la versión "más cercana" según sus reglas de mediación de dependencia y emitirá una advertencia "Tenemos una clase duplicada ..." Si una firma de método / clase cambia entre las versiones, puede causar una excepción java.lang.IncompatibleClassChangeError si la versión incorrecta se utiliza en tiempo de ejecución.

Avanzado: si A debe usar v1 de C y B debe usar v2 de C , entonces debemos relocate C en los poms de A y B para evitar conflictos de clase (tenemos una advertencia de clase duplicada) al crear el proyecto final que depende de ambos A y B


Esto significa que ha realizado algunos cambios binarios incompatibles en la biblioteca sin volver a compilar el código del cliente. La Especificación del lenguaje Java §13 detalla todos estos cambios, principalmente, cambiando los campos / métodos no static no privados para que sean static o viceversa.

Vuelva a compilar el código del cliente contra la nueva biblioteca, y debería estar listo.

ACTUALIZACIÓN: si publica una biblioteca pública, debe evitar realizar cambios binarios incompatibles tanto como sea posible para preservar lo que se conoce como "compatibilidad con versiones anteriores binarias". La actualización de los tarros de dependencia por sí sola, idealmente, no debería romper la aplicación o la compilación. Si tiene que romper la compatibilidad con versiones anteriores binarias, se recommended aumentar el número de la versión principal (por ejemplo, de 1.xy a 2.0.0) antes de lanzar el cambio.


He enfrentado este problema mientras desplegaba y redesplegaba una guerra con glassfish. Mi estructura de clase era así,

public interface A{ } public class AImpl implements A{ }

y se cambió a

public abstract class A{ } public class AImpl extends A{ }

Después de detener y reiniciar el dominio, funcionó bien. Yo estaba usando glassfish 3.1.43


Mi respuesta, creo, será específica de Intellij.

Yo había reconstruido limpio, incluso yendo tan lejos como para eliminar manualmente los directorios "out" y "target". Intellij tiene un "invalidar cachés y reiniciar", que a veces borra errores impares. Esta vez no funcionó. Todas las versiones de dependencia parecían correctas en la configuración del proyecto -> menú de módulos.

La respuesta final fue eliminar manualmente mi dependencia del problema de mi repositorio local. Una versión antigua de bouncycastle fue la culpable (sabía que acababa de cambiar las versiones y ese sería el problema) y aunque la versión anterior no aparecía en qué parte de lo que se estaba construyendo, resolvió mi problema. Estaba usando intellij versión 14 y luego actualicé a 15 durante este proceso.


Otra situación en la que puede aparecer este error es con Emma Code Coverage.

Esto sucede cuando se asigna un objeto a una interfaz. Supongo que esto tiene algo que ver con el Objeto que está siendo instrumentado y que ya no es compatible con binarios.

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

Afortunadamente, este problema no ocurre con Cobertura, por lo que he agregado cobertura-maven-plugin en mis complementos de informes de mi pom.xml


Por alguna razón, también se lanza la misma excepción cuando se usa JNI y se pasa el argumento jclass en lugar del trabajo al llamar a un Call*Method() .

Esto es similar a la respuesta del Salmo de Ogre33.

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

Sé que es un poco tarde para responder a esta pregunta 5 años después de ser preguntado, pero este es uno de los mejores éxitos al buscar java.lang.IncompatibleClassChangeError así que quería documentar este caso especial.


Si bien todas estas respuestas son correctas, resolver el problema suele ser más difícil. En general, es el resultado de dos versiones ligeramente diferentes de la misma dependencia en la ruta de clase, y casi siempre es causada por una superclase diferente de la que se compiló originalmente contra la clase o por la importancia del cierre transitivo, pero generalmente en clase La instanciación y la invocación del constructor. (Después de la carga exitosa de la clase y la invocación de ctor, obtendrás NoSuchMethodException o todo eso).

Si el comportamiento parece aleatorio, es probable que sea el resultado de una clase de programa multiproceso que carga diferentes dependencias transitivas en función de qué código se golpeó primero.

Para resolver esto, intente iniciar la máquina virtual con -verbose como un argumento, luego observe las clases que se estaban cargando cuando se produce la excepción. Deberías ver alguna información sorprendente. Por ejemplo, tener copias múltiples de la misma dependencia y versiones que nunca esperó o que habría aceptado si supiera que estaban incluidas.

La resolución de los tarros duplicados con Maven se realiza mejor con una combinación del maven-dependency-plugin maven-enforcer-plugin y el maven-dependency-plugin maven-enforcer-plugin bajo Maven (o el complemento de gráfico de dependencia de SBT, luego se agregan esos tarros a una sección de su POM de nivel superior o como dependencia importada Elementos en SBT (para eliminar esas dependencias).

¡Buena suerte!


Si este es un registro de las posibles ocurrencias de este error, entonces:

Acabo de recibir este error en WAS (8.5.0.1), durante la carga de CXF (2.6.0) de la configuración de la primavera (3.1.1_release) donde una BeanInstantiationException acumuló una CXF ExtensionException, enrollando una IncompatibleClassChangeError. El siguiente fragmento de código muestra la esencia de la traza de la pila:

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

En este caso, la solución fue cambiar el orden de classpath del módulo en mi archivo war. Es decir, abra la aplicación de guerra en la consola WAS debajo y seleccione el (los) módulo (s) cliente (s). En la configuración del módulo, establezca que la carga de clase sea "padre último".

Esto se encuentra en la consola WAS:

  • Aplicaciones -> Tipos de aplicaciones -> Aplicaciones empresariales de WebSphere
  • Haga clic en el enlace que representa su aplicación (guerra)
  • Haga clic en "Administrar módulos" en la sección "Módulos"
  • Haga clic en el enlace para el módulo (s) subyacente (s)
  • Cambie "Orden del cargador de clases" para que sea "(último padre)".

Su biblioteca recién empaquetada no es compatible con versiones anteriores binarias (BC) con la versión anterior. Por esta razón, algunos de los clientes de la biblioteca que no están recompilados pueden lanzar la excepción.

Esta es una lista completa de los cambios en la API de la biblioteca de Java que pueden provocar que los clientes creados con una versión anterior de la biblioteca lancen java.lang. IncompatibleClassChangeError si se ejecutan en uno nuevo (es decir, rompiendo BC):

  1. El campo no final se vuelve estático,
  2. El campo no constante se vuelve no estático,
  3. Clase convertida en interfaz,
  4. Interfaz convertido en clase,
  5. Si agrega un nuevo campo a la clase / interfaz (o agrega una nueva super-clase / super-interfaz), entonces un campo estático de una super-interfaz de un cliente de clase C puede ocultar un campo agregado (con el mismo nombre) heredado de la Superclase de C (caso muy raro).

Nota : Hay muchas otras excepciones causadas por otros cambios incompatibles: NoSuchFieldError , NoSuchMethodError , IllegalAccessError , InstantiationError , VerifyError , NoClassDefFoundError y AbstractMethodError .

El mejor artículo sobre BC es "Evolving API-based 2: Achieving API Binary Compatibility" escrito por Jim des Rivières.

También hay algunas herramientas automáticas para detectar tales cambios:

Uso de japi-compliance-checker para su biblioteca:

japi-compliance-checker OLD.jar NEW.jar

Uso de la herramienta clirr:

java -jar clirr-core-0.6-uber.jar -o OLD.jar -n NEW.jar

¡Buena suerte!


También descubrí que, al usar JNI, invocar un método Java desde C ++, si pasa los parámetros al método Java invocado en el orden incorrecto, obtendrá este error cuando intente usar los parámetros dentro del método llamado (porque no será el tipo correcto). Inicialmente, me sorprendió que JNI no haga esta comprobación para usted como parte de la comprobación de la firma de la clase cuando invoque el método, pero supongo que no hacen este tipo de comprobación porque puede pasar parámetros polimórficos y tienen que asume que sabes lo que estás haciendo.

Ejemplo de código 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. }

Ejemplo de código 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... } } }


Tengo una aplicación web que se implementa perfectamente bien en el tomcat de mi máquina local (8.0.20). Sin embargo, cuando lo puse en el entorno qa (tomcat - 8.0.20), siguió dándome IncompatibleClassChangeError y se quejaba de que me estaba extendiendo en una interfaz. Esta interfaz se cambió a una clase abstracta. Y compilé las clases para padres e hijos y aún así seguí teniendo el mismo problema. Finalmente, quise depurar, así que, cambié la versión del padre a x.0.1-SNAPSHOT y luego compilé todo y ahora está funcionando. Si alguien sigue teniendo el problema después de seguir las respuestas que se dan aquí, asegúrese de que las versiones en su pom.xml también sean correctas. Cambia las versiones para ver si eso funciona. Si es así, entonces arregla el problema de la versión.


Todo lo anterior, por la razón que sea que estaba haciendo un gran refactor y empezando a obtener esto. Cambié el nombre del paquete en el que estaba mi interfaz y eso lo borró. Espero que ayude.


Una causa adicional de este problema es si tiene la Instant Run habilitada para Android Studio.

La solución

Si encuentra que comienza a recibir este error, desactive la Instant Run .

  1. Ajustes principales de Android Studio
  2. Construir, Ejecución, Despliegue
  3. Ejecución instantánea
  4. Desmarque "Habilitar ejecución instantánea ..."

Por qué

Instant Run modifica una gran cantidad de cosas durante el desarrollo, para que sea más rápido proporcionar actualizaciones a su aplicación en ejecución. De ahí la ejecución instantánea. Cuando funciona, es realmente útil. Sin embargo, cuando surge un problema como este, lo mejor que puede hacer es desactivar la Instant Run hasta la próxima versión de Android Studio.


Tuve el mismo problema, y ​​luego me di cuenta de que estoy ejecutando la aplicación en la versión 1.4 de Java mientras la aplicación está compilada en la versión 6.

En realidad, la razón era tener una biblioteca duplicada, una se encuentra dentro de la ruta de clase y la otra se incluye dentro de un archivo jar que se encuentra dentro de la ruta de clase.