Estoy empaquetando una biblioteca Java como JAR, y arroja muchos correos java.lang.IncompatibleClassChangeError
electrónicos cuando trato de invocar métodos. Estos errores parecen aparecer al azar. ¿Qué tipo de problemas podrían estar causando este error?
218
Respuestas:
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, lo más importante, cambiando
static
los campos / métodos no privados para que seanstatic
o viceversa.Vuelva a compilar el código del cliente con la nueva biblioteca, y debería estar listo.
ACTUALIZACIÓN: Si publica una biblioteca pública, debe evitar hacer cambios binarios incompatibles tanto como sea posible para preservar lo que se conoce como "compatibilidad binaria hacia atrás". La actualización de los archivos jar de dependencia por sí solo no debería romper la aplicación o la compilación. Si tiene que romper la compatibilidad con versiones anteriores binarias, se recomienda aumentar el número de versión principal (por ejemplo, de 1.xy a 2.0.0) antes de lanzar el cambio.
fuente
*.class
archivos) y volver a compilar? La edición de archivos tiene un efecto similar.Su biblioteca recién empaquetada no es compatible con binarios anteriores (BC) con la versión anterior. Por esta razón, algunos de los clientes de la biblioteca que no se vuelven a compilar pueden generar la excepción.
Esta es una lista completa de los cambios en la API de la biblioteca Java que pueden hacer que los clientes compilados con una versión anterior de la biblioteca arrojen java.lang. IncompatibleClassChangeError si se ejecutan en uno nuevo (es decir, romper BC):
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 "Evolución de las API 2 basadas en Java: lograr la compatibilidad binaria de API", 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:
Uso de la herramienta clirr:
¡Buena suerte!
fuente
Si bien todas estas respuestas son correctas, resolver el problema suele ser más difícil. Generalmente es el resultado de dos versiones ligeramente diferentes de la misma dependencia en el classpath, y casi siempre es causada por una superclase diferente de la que se compiló originalmente contra el classpath o por alguna importación del cierre transitivo diferente, pero generalmente en clase instanciación e invocación del constructor. (Después de la carga exitosa de la clase y la invocación del ctor, obtendrá
NoSuchMethodException
o no).Si el comportamiento parece aleatorio, es probable que el resultado de un programa multiproceso que cargue diferentes dependencias transitivas en función del código que se golpeó primero.
Para resolver esto, intente iniciar la VM con
-verbose
un argumento, luego observe las clases que se estaban cargando cuando se produce la excepción. Deberías ver información sorprendente. Por ejemplo, tener múltiples copias de la misma dependencia y versiones que nunca esperó o habría aceptado si supiera que se están incluyendo.La resolución de frascos duplicados con Maven se realiza mejor con una combinación de maven-dependency-plugin y maven-enforcer-plugin en Maven (o el Dependency Graph Plugin de SBT , luego agrega esos frascos a una sección de tu POM de nivel superior o como dependencia importada elementos en SBT (para eliminar esas dependencias).
¡Buena suerte!
fuente
También descubrí que, al usar JNI, invocando 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 verificación por usted como parte de la verificación de firma de clase cuando invoca el método, pero supongo que no hacen este tipo de verificación porque puede estar pasando parámetros polimórficos y tienen que Asume que sabes lo que estás haciendo.
Ejemplo de código C ++ JNI:
Código Java de ejemplo:
fuente
Tuve el mismo problema, y luego descubrí que estoy ejecutando la aplicación en Java versión 1.4 mientras la aplicación se compila en la versión 6.En realidad, la razón era tener una biblioteca duplicada, una se encuentra dentro del classpath y la otra se incluye dentro de un archivo jar que se encuentra dentro del classpath.
fuente
Otra situación en la que puede aparecer este error es con Emma Code Coverage.
Esto sucede al asignar un objeto a una interfaz. Supongo que esto tiene algo que ver con el objeto que está siendo instrumentado y 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
fuente
Me he enfrentado a este problema al desplegar y volver a desplegar una guerra con glassfish. Mi estructura de clase era así,
y fue cambiado a
Después de detener y reiniciar el dominio, funcionó bien. Estaba usando glassfish 3.1.43
fuente
Tengo una aplicación web que se implementa perfectamente en el tomcat de mi máquina local (8.0.20). Sin embargo, cuando lo puse en el entorno qa (tomcat - 8.0.20), me seguía dando el 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 seguía teniendo el mismo problema. Finalmente, quería 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 resolviendo 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. Cambie las versiones para ver si eso funciona. Si es así, solucione el problema de la versión.
fuente
Mi respuesta, creo, será específica de Intellij.
Había reconstruido limpio, incluso llegando a eliminar manualmente los directorios "out" y "target". Intellij tiene un "invalidar cachés y reiniciar", que a veces borra errores extraños. Esta vez no funcionó. Todas las versiones de dependencia parecían correctas en el menú de configuración del proyecto-> módulos.
La respuesta final fue eliminar manualmente la dependencia de mi problema de mi repositorio local de Maven. El culpable era una versión anterior de Bouncycastle (sabía que acababa de cambiar las versiones y ese sería el problema) y aunque la versión anterior no apareció en ningún lugar de lo que se estaba construyendo, resolvió mi problema. Estaba usando intellij versión 14 y luego actualicé a 15 durante este proceso.
fuente
En mi caso, me encontré con este error de esta manera.
pom.xml
de mi proyecto definió dos dependenciasA
yB
. Y ambasA
y laB
dependencia definida en el mismo artefacto (llámeloC
) pero diferentes versiones del mismo (C.1
yC.2
). Cuando esto sucede, para cada clase enC
maven solo se puede seleccionar una versión de la clase de las dos versiones (mientras se crea un uber-jar ). Seleccionará la versión "más cercana" en función de sus reglas de mediación de dependencia y generará una advertencia "Tenemos una clase duplicada ..." Si una firma de método / clase cambia entre las versiones, puede causar unajava.lang.IncompatibleClassChangeError
excepción si la versión incorrecta es utilizado en tiempo de ejecución.Avanzado: si
A
debe usar v1 deC
yB
debe usar v2 deC
, entonces debemos reubicarnosC
enA
yB
poms para evitar conflictos de clase (tenemos una advertencia de clase duplicada) al construir el proyecto final que depende de ambosA
yB
.fuente
En mi caso, el error apareció cuando agregué la
com.nimbusds
biblioteca en mi aplicación implementadaWebsphere 8.5
.Se produjo la siguiente excepción:
La solución fue excluir el jar asm de la biblioteca:
fuente
Compruebe si su código no consta de dos proyectos de módulo que tengan los mismos nombres de clases y la misma definición de paquetes. Por ejemplo, esto podría suceder si alguien usa copiar y pegar para crear una nueva implementación de la interfaz basada en la implementación anterior.
fuente
Si este es un registro de posibles ocurrencias de este error, entonces:
Acabo de recibir este error en WAS (8.5.0.1), durante la carga CXF (2.6.0) de la configuración de resorte (3.1.1_release) donde una excepción BeanInstantiationException acumula una excepción CXF ExtensionException, acumulando un IncompatibleClassChangeError. El siguiente fragmento muestra la esencia del seguimiento de la pila:
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 war en la consola WAS y seleccione los módulos del cliente. En la configuración del módulo, establezca la carga de clase en "padre último".
Esto se encuentra en la consola WAS:
fuente
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.
Teníamos un archivo jar común que tenía una
@local
anotación. Esa clase luego se mudó de ese proyecto común a nuestro proyecto principal de ejb jar. Nuestra jarra ejb y nuestra jarra común están agrupadas dentro de una oreja. La versión de nuestra dependencia jar común no se actualizó. Así 2 clases intentan ser algo con cambios incompatibles.fuente
Todo lo anterior: por cualquier razón, estaba haciendo un gran refactor y comenzando a obtener esto. Cambié el nombre del paquete en el que estaba mi interfaz y eso lo borró. Espero que ayude.
fuente
Por alguna razón, la misma excepción también se produce cuando se usa JNI y se pasa el argumento jclass en lugar del objeto de trabajo cuando se llama a
Call*Method()
.Esto es similar a la respuesta de Ogre Psalm33.
Sé que es un poco tarde para responder esta pregunta 5 años después de haber sido preguntado, pero este es uno de los principales éxitos al buscar,
java.lang.IncompatibleClassChangeError
así que quería documentar este caso especial.fuente
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 suceden debido a diferentes nombres que conducen a errores de tiempo de ejecución al iniciar la aplicación scala.
fuente
Una causa adicional de este problema es si ha
Instant Run
habilitado para Android Studio.La solución
Si encuentra que comienza a recibir este error, desactívelo
Instant Run
.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 es apagarInstant Run
hasta la próxima versión de Android Studio.fuente