Co powoduje java.lang.IncompatibleClassChangeError?

Pakuję bibliotekę Javy jako JAR i wyrzuca ona wiele java.lang.IncompatibleClassChangeError s, gdy próbuję wywołać z niej metody. Błędy te wydają się pojawiać przypadkowo. Jakie problemy mogą być przyczyną tego błędu?

Author: Pops, 2009-12-30

17 answers

Oznacza to, że dokonałeś pewnych niekompatybilnych zmian binarnych w bibliotece bez rekompilacji kodu klienta. specyfikacja języka Java §13 wyszczególnia wszystkie takie zmiany, najczęściej zmieniając Nie-static nie-prywatne pola / metody na static lub odwrotnie.

Przekompiluj kod klienta z nową biblioteką i powinieneś być gotowy.

UPDATE: jeśli publikujesz Bibliotekę Publiczną, powinieneś unikać wprowadzania niezgodnych zmian binarnych tak bardzo, jak to możliwe aby zachować tzw. "binarną kompatybilność wsteczną". Aktualizowanie samych jarów zależności najlepiej nie powinno niszczyć aplikacji ani kompilacji. Jeśli musisz złamać wsteczną kompatybilność binarną, to zaleca się zwiększenie głównego numeru wersji (np. z 1.x. y do 2.0.0) przed wydaniem zmiany.

 149
Author: notnoop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-23 09:21:50

Twoja nowo spakowana biblioteka nie jest wstecznie kompatybilna binarnie (BC) ze starą wersją. Z tego powodu niektóre z klientów biblioteki, które nie są rekompilowane, mogą wyrzucić wyjątek.

Jest to Pełna Lista zmian w java library API, które mogą spowodować, że klienci zbudowani ze starszą wersją biblioteki rzucają Javę.lang.IncompatibleClassChangeError jeśli działają na nowym (np. łamanie BC):

  1. Pole niekończące się staje się static,
  2. nie-stałe pole staje się nie-statyczne,
  3. Class become interface,
  4. Interface become class,
  5. jeśli dodasz nowe pole do klasy / interfejsu (lub dodasz nową super-klasę / super-interfejs), statyczne pole z super-interfejsu klienta klasy C może ukryć dodane pole (o tej samej nazwie) odziedziczone po super-klasie C (bardzo rzadki przypadek).

Uwaga: Istnieje wiele innych wyjątków spowodowanych przez inne niezgodne zmiany: NoSuchFieldError, NoSuchMethodError, IllegalAccessError, InstantiationError, VerifyError, NoClassDefFoundError i AbstractMethodError.

Lepszym artykułem o BC jest"Evolving Java-based API 2: Achieving API Binary Compatibility" napisany przez Jima des Rivières.

Istnieje również kilka automatycznych narzędzi do wykrywania takich zmiany:

Użycie japi-compliance-checker dla twojej Biblioteki:

japi-compliance-checker OLD.jar NEW.jar

Użycie narzędzia clirr:

java -jar clirr-core-0.6-uber.jar -o OLD.jar -n NEW.jar
Powodzenia!
 92
Author: linuxbuild,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-20 08:57:38

Chociaż wszystkie te odpowiedzi są poprawne, rozwiązanie problemu jest często trudniejsze. Jest to na ogół wynik dwóch nieco różnych wersji tej samej zależności od classpath i jest prawie zawsze spowodowane albo inną klasą nadrzędną niż pierwotnie skompilowana przed byciem na classpath lub pewnym importem przechodniego zamknięcia, które jest inne, ale ogólnie przy instancjacji klasy i wywołaniu konstruktora. (Po udanym załadowaniu klasy i ctor inwokacja, dostaniesz NoSuchMethodException czy coś.)

Jeśli zachowanie wydaje się przypadkowe, jest to prawdopodobnie wynik wielowątkowej klasy programu, która ładuje różne zależności przechodnie w zależności od tego, który Kod został trafiony pierwszy.

Aby je rozwiązać, spróbuj uruchomić maszynę wirtualną z -verbose jako argumentem, a następnie spójrz na klasy, które były ładowane, gdy wystąpi wyjątek. Powinieneś zobaczyć zaskakujące informacje. Na przykład, mając wiele kopii tej samej zależności i wersji nigdy oczekiwał lub zaakceptowałby, gdybyś wiedział, że są włączone.

Rozwiązywanie zduplikowanych jarów za pomocą Mavena najlepiej wykonać za pomocą kombinacji Maven-dependency-plugin i maven-Enforcer-plugin Pod Maven (lub wtyczki grafu zależności SBT , a następnie dodać te Jary do sekcji twojego najwyższego poziomu POM lub jako importowane elementy zależności w SBT (aby usunąć te zależności).

Powodzenia!
 51
Author: Brian Topping,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-30 21:52:45

Odkryłem również, że podczas używania JNI, wywołania metody Java z C++, jeśli przekażesz parametry do wywołanej metody Java w złej kolejności, pojawi się ten błąd podczas próby użycia parametrów wewnątrz wywołanej metody (ponieważ nie będą one właściwym typem). Początkowo byłem zaskoczony, że JNI nie robi tego sprawdzania dla Ciebie w ramach sprawdzania podpisu klasy podczas wywoływania metody, ale zakładam, że nie robią tego rodzaju sprawdzania, ponieważ możesz zdać parametry polimorficzne i muszą zakładać, że wiesz, co robisz.

Przykładowy kod 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.
}

Przykładowy Kod Javy:

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...
        }
    }
}
 4
Author: Ogre Psalm33,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-16 16:44:27

miałem ten sam problem, a później zorientowałem się, że uruchamiam aplikację na Javie w wersji 1.4, podczas gdy aplikacja jest skompilowana na wersji 6.

W rzeczywistości powodem było posiadanie zduplikowanej biblioteki, jedna znajduje się w ścieżce klasowej, a druga jest zawarta w pliku jar, który znajduje się w ścieżce klasowej.

 4
Author: Eng.Fouad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-16 11:04:42

Inną sytuacją, w której może pojawić się ten błąd, jest pokrycie kodu Emmy.

Dzieje się tak przy przypisywaniu obiektu do interfejsu. Myślę, że ma to coś wspólnego z tym, że obiekt jest instrumentowany i nie jest już kompatybilny z binarnymi.

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

Na szczęście ten problem nie występuje z Coberturą, więc dodałem cobertura-maven-plugin w moich wtyczkach raportujących mojego pom.xml

 1
Author: stivlo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-08 12:33:32

Miałem do czynienia z tym problemem podczas unploying i ponaglania wojny z glassfish. Moja struktura klasowa była taka,

public interface A{
}

public class AImpl implements A{
}

I została zmieniona na

public abstract class A{
}

public class AImpl extends A{
}

Po zatrzymaniu i ponownym uruchomieniu domeny działało dobrze. Używałem glassfish 3.1.43

 1
Author: Nerrve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-06 07:20:55

Mam aplikację internetową, która działa doskonale na moim lokalnym komputerze tomcat (8.0.20). Jednak, kiedy umieściłem go w środowisku qa (tomcat - 8.0.20), nadal dawał mi IncompatibleClassChangeError i narzekał, że rozszerzam interfejs. Interfejs ten został zmieniony na klasę abstrakcyjną. I skompilowałem zajęcia dla rodziców i dzieci i nadal otrzymywałem ten sam problem. W końcu chciałem debugować, więc zmieniłem wersję na rodzicu na x. 0. 1-migawka, a następnie skompilowane wszystko i teraz działa. Jeśli ktoś nadal uderza w problem po wykonaniu odpowiedzi podanych tutaj, upewnij się, że wersje w Twoim pom.xml są również poprawne. Zmień wersje, aby sprawdzić, czy to działa. Jeśli tak, napraw problem z wersją.

 1
Author: Jobin Thomas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-25 19:04:57

Moja odpowiedź, wierzę, będzie Intellij konkretne.

Przebudowałem clean, nawet posuwając się do ręcznego usuwania" out "i" target " dirs. Intellij ma "invalidate caches and restart", który czasami usuwa dziwne błędy. Tym razem się nie udało. Wszystkie wersje zależności wyglądały poprawnie w menu Ustawienia projektu- > Moduły.

Ostateczną odpowiedzią było ręczne usunięcie zależności problemu z mojego lokalnego repo maven. Stara wersja bouncycastle była winowajca (wiedziałem, że właśnie zmieniłem wersje i w tym będzie problem) i chociaż stara wersja nie pokazała gdzie w tym co jest budowane, rozwiązała mój problem. Używałem intellij w wersji 14, a następnie uaktualniłem do 15 podczas tego procesu.

 1
Author: David Nickerson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-16 20:28:12

W moim przypadku, wpadłem na ten błąd w ten sposób. pom.xml mojego projektu zdefiniowały dwie zależności A i B. I zarówno A, jak i B zdefiniowały zależność od tego samego artefaktu (nazwij go C), ale różne jego wersje (C.1 i C.2). Gdy tak się stanie, dla każdej klasy w C maven może wybrać tylko jedną wersję klasy z dwóch wersji (podczas budowania uber-jar ). Wybierze "najbliższą" wersję na podstawie swoich reguł mediacji zależności i wyświetli Ostrzeżenie " mamy duplikat klasy..." jeśli sygnatura metody/klasy zmienia się między wersjami, może to spowodować wyjątek java.lang.IncompatibleClassChangeError, jeśli w czasie wykonywania używana jest nieprawidłowa wersja.

Zaawansowane: Jeśli A musi używać v1 z C i B musi używać v2 z C, to musimy przenieść C W A i B'S poms, aby uniknąć konfliktu klas (mamy duplikat Ostrzeżenia klasy) podczas budowania końcowego projektu, który zależy zarówno od A i B.

 1
Author: morpheus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:08

Proszę sprawdzić, czy kod nie składa się z dwóch projektów modułów, które mają te same nazwy klas i definicję pakietów. Na przykład może się to zdarzyć, jeśli ktoś używa copy-paste do tworzenia nowej implementacji interfejsu w oparciu o poprzednią implementację.

 0
Author: denu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-25 07:56:49

Jeśli jest to zapis możliwych wystąpień tego błędu to:

Właśnie dostałem ten błąd na WAS (8.5.0.1), podczas ładowania CXF (2.6.0) konfiguracji spring (3.1.1_release), gdzie Beaninstantationexception zwijał CXF ExtensionException, zwijając Incompatbleclasschangeerror. Poniższy fragment pokazuje gist śladu stosu:

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

W tym przypadku rozwiązaniem była zmiana kolejności klas modułu w moim pliku war. Czyli otwórz war aplikacji w konsoli był pod i wybrać moduł klienta(s). W konfiguracji modułu Ustaw klasę-loading na "parent last".

To znajduje się w konsoli WAS:

  • Applicatoins -> Typy Aplikacji - > Aplikacje WebSphere Enterprise
  • Kliknij link przedstawiający Twoją aplikację (war)
  • Kliknij "Zarządzaj modułami" w sekcji "Moduły"
  • Kliknij link do podstawowego modułu
  • Zmień "Class loader order" na "(parent last)".
 0
Author: wmorrison365,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-20 16:38:23

Dokumentowanie innego scenariusza po spaleniu zbyt dużo czasu.

Upewnij się, że nie masz pliku zależności, który ma klasę z adnotacją EJB.

Mieliśmy wspólny plik jar, który miał adnotację @local. Ta klasa została później przeniesiona z tego wspólnego projektu do naszego głównego projektu EJB jar. Nasz ejb jar i nasz wspólny jar są połączone w ucho. Wersja naszej zależności common jar nie została zaktualizowana. Tak więc 2 klasy starają się być czymś z niezgodne zmiany.

 0
Author: Snekse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-09 18:53:14

Wszystkie powyższe-z jakiegokolwiek powodu robiłem jakiś duży refaktor i zacząłem to rozumieć. Zmieniłem nazwę pakietu, w którym był mój interfejs i to go wyczyściło. Mam nadzieję, że to pomoże.

 0
Author: bsautner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-17 19:36:15

Z jakiegoś powodu ten sam wyjątek jest również wyrzucany podczas używania JNI i przekazywania argumentu jclass zamiast jobject podczas wywoływania Call*Method().

Jest to podobne do odpowiedzi Z Ogre Psalm33.

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

Wiem, że jest trochę późno, aby odpowiedzieć na to pytanie 5 lat po zadaniu, ale jest to jeden z najlepszych hitów podczas wyszukiwania java.lang.IncompatibleClassChangeError więc chciałem udokumentować ten szczególny przypadek.

 0
Author: Eric Obermühlner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-23 19:03:32

Dodaję moje 2 centy .Jeśli używasz scala i sbt oraz Scala-logging jako zależności; wtedy może się to zdarzyć, ponieważ wcześniejsza wersja Scala-logging miała nazwę scala-logging-api.So; zasadniczo rozwiązywanie zależności nie występuje z powodu różnych nazw prowadzących do błędów podczas uruchamiania aplikacji scala.

 0
Author: sourabh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-19 13:47:21

Dodatkową przyczyną tego problemu jest włączenie Instant Run dla Android Studio.

The fix

Jeśli zauważysz, że zaczynasz otrzymywać ten błąd, wyłącz Instant Run.

  1. Android Studio main settings
  2. Budowa, Wykonanie, Wdrożenie
  3. Instant Run
  4. Untick " Włącz natychmiastowe uruchamianie..."

Dlaczego

Instant Run modyfikuje wiele rzeczy podczas tworzenia aplikacji, aby szybciej dostarczać aktualizacje do uruchomionej aplikacji. Stąd natychmiastowy bieg. Kiedy to działa, to jest naprawdę przydatne. Jednak, gdy pojawia się taki problem, najlepiej wyłączyć Instant Run do czasu wydania kolejnej wersji Android Studio.

 0
Author: Knossos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-27 11:14:58