IncompatibleClassChangeError без трассировки стека [дубликат]

Если вы используете GitUp , выберите фиксацию, которую хотите объединить с ее родителем, и нажмите S. Вы должны сделать это один раз для каждой фиксации, но это намного проще, чем придумать правильное заклинание командной строки. Особенно, если это то, что вы делаете только время от времени.

188
задан Pops 14 February 2012 в 20:11
поделиться

17 ответов

Это означает, что вы внесли некоторые несовместимые двоичные изменения в библиотеку без перекомпиляции кода клиента. Спецификация языка Java §13 описывает все такие изменения, наиболее заметно, изменение нефайловых полей / методов не static как static или наоборот.

Перекомпилировать клиентский код против новой библиотеки, и вам должно быть хорошо идти.

UPDATE: если вы публикуете публичную библиотеку, вы должны избегать несовместимых двоичных изменений в максимально возможной степени, чтобы сохранить так называемое «двоичное обратное» совместимость". Обновление баннеров зависимостей в идеале не должно нарушать приложение или сборку. Если вам нужно нарушить двоичную обратную совместимость, рекомендуется увеличить основной номер версии (например, от 1.x.y до 2.0.0), прежде чем отпускать изменение.

147
ответ дан user833771 26 August 2018 в 15:49
поделиться

Хотя эти ответы правильны, решение проблемы часто бывает более сложным. Это, как правило, результат двух слегка разных версий одной и той же зависимости от пути к классам и почти всегда вызван либо другим суперклассом, чем он был первоначально скомпилирован против того, чтобы быть на пути к классам или некоторая импорт транзитивного закрытия будучи разными, но обычно при создании экземпляра класса и вызове конструктора. (После успешной загрузки класса и вызова ctor вы получите NoSuchMethodException или еще что-то.)

Если поведение кажется случайным, это, скорее всего, результат многопоточной загрузки программ с различными транзитивными зависимостями на основе того, какой код получил удар первым.

Чтобы решить эту проблему, попробуйте запустить VM с -verbose в качестве аргумента, а затем посмотрите на классы, которые были загружены при возникновении исключения. Вы должны увидеть удивительную информацию. Например, наличие нескольких копий одной и той же зависимости и версий, которые вы никогда не ожидали или не приняли бы, если бы знали, что они включены.

Решение дублировать банки с Maven лучше всего сделать с помощью комбинации maven-dependency-plugin и maven-enforcer-plugin в Maven (или SBT плагин графика зависимостей , а затем добавление этих банок в раздел вашего верхнего уровня POM или импортированные элементы зависимостей в SBT (для удаления этих зависимостей).

Удачи!

51
ответ дан Brian Topping 26 August 2018 в 15:49
поделиться

Все вышесказанное - по какой-то причине я делал большой рефакторинг и начал это делать. Я переименовал пакет, в котором находился мой интерфейс, и который очистил его. Надеюсь, что это поможет.

0
ответ дан bsautner 26 August 2018 в 15:49
поделиться

В моем случае я столкнулся с этой ошибкой таким образом. pom.xml моего проекта определили две зависимости A и B. И оба A, и B определяют зависимость от того же артефакта (назовите его C), но разные версии его (C.1 и C.2). Когда это произойдет, для каждого класса в C maven может выбрать только одну версию класса из двух версий (при создании uber-jar ). Он выберет «ближайшую» версию на основе своих правил посредничества и выведет предупреждение «У нас есть повторяющийся класс ...» Если изменяется подпись метода / класса

Дополнительно: Если A должен использовать v1 из C, а B должен использовать v2 из C, то мы должны переместить C в poms A и B, чтобы избежать конфликта классов (у нас есть предупреждение о повторяющихся классах) при построении окончательного проекта, который зависит как от обоих A и B.

1
ответ дан Community 26 August 2018 в 15:49
поделиться

Мой ответ, я считаю, будет Intellij специфическим.

Я восстановил чистоту, даже до тех пор, пока не удалил вручную «выходные» и «целевые». Intellij имеет «недействительные кеши и перезапуск», который иногда очищает нечетные ошибки. На этот раз это не сработало. Все версии зависимостей выглядели корректно в меню настроек проекта -> modules.

Последний ответ заключался в том, чтобы вручную удалить мою проблему из моего локального репозитория maven. Старая версия bouncycastle была виновницей (я знал, что я только что изменил версии, и это будет проблемой), и хотя в старой версии не было места, где строилось, она решила мою проблему. Я использовал intellij версии 14, а затем был обновлен до 15 во время этого процесса.

1
ответ дан David Nickerson 26 August 2018 в 15:49
поделиться

Пожалуйста, проверьте, не содержит ли ваш код два проекта модулей, которые имеют одинаковые определения классов и пакетов. Например, это может произойти, если кто-то использует copy-paste для создания новой реализации интерфейса на основе предыдущей реализации.

0
ответ дан denu 26 August 2018 в 15:49
поделиться

У меня была та же проблема, и позже я понял, что я запускаю приложение на Java версии 1.4, в то время как приложение скомпилировано в версии 6.

На самом деле, причина заключалась в наличии дублированной библиотеки , один находится внутри пути к классам, а другой - внутри файла jar, который находится внутри пути к классам.

4
ответ дан Eng.Fouad 26 August 2018 в 15:49
поделиться

По какой-то причине одно и то же исключение также возникает при использовании JNI и передаче аргумента jclass вместо jobject при вызове Call*Method().

Это похоже на ответ от 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;
}

Я знаю, что немного поздно ответить на этот вопрос через 5 лет после того, как его спросили, но это один из лучших ударов при поиске java.lang.IncompatibleClassChangeError, поэтому я хотел задокументировать этот специальный случай.

0
ответ дан Eric Obermühlner 26 August 2018 в 15:49
поделиться

У меня есть веб-приложение, которое отлично отлично работает на tomcat моей локальной машины (8.0.20). Однако, когда я помещал его в среду qa (tomcat - 8.0.20), он продолжал давать мне IncompatibleClassChangeError, и он жаловался, что я расширялся на интерфейсе. Этот интерфейс был изменен на абстрактный класс. И я скомпилировал родительский и дочерний классы, и все же я продолжал получать ту же проблему. Наконец, я хотел отлаживать, поэтому я изменил версию родителя на x.0.1-SNAPSHOT, а затем скомпилировал все, и теперь он работает. Если кто-то все еще сталкивается с проблемой после следующих ответов, пожалуйста, убедитесь, что версии в вашем pom.xml также верны. Измените версии, чтобы увидеть, работает ли это. Если да, то исправьте проблему с версией.

1
ответ дан Jobin Thomas 26 August 2018 в 15:49
поделиться

Дополнительной причиной этой проблемы является использование Instant Run для Android Studio.

Исправить

Если вы обнаружите, что вы начали получать эту ошибку, выключите Instant Run.

  1. Основные настройки Android Studio
  2. Сборка, выполнение, развертывание
  3. Мгновенный запуск
  4. Untick «Включить мгновенный запуск ... "

Почему

Instant Run изменяет большое количество вещей во время разработки, чтобы быстрее было обновлять текущее приложение. Следовательно, мгновенный запуск. Когда это работает, это действительно полезно. Однако, когда проблема, подобная этой проблеме, лучше всего отключить Instant Run, пока не будет выпущена следующая версия Android Studio.

0
ответ дан Knossos 26 August 2018 в 15:49
поделиться

Ваша недавно упакованная библиотека не поддерживает обратную двоичную совместимость (BC) со старой версией. По этой причине некоторые из клиентов библиотеки, которые не перекомпилированы, могут генерировать исключение.

Это полный список изменений в API библиотек Java, который может привести к тому, что клиенты, созданные со старой версией библиотеки, будут бросать java .lang.IncompatibleClassChangeError, если они работают на новом (например, разрыв BC):

  1. Не конечное поле становится статическим,
  2. Непостоянное поле становится нестатичным,
  3. Класс станет интерфейсом,
  4. Интерфейс станет классом,
  5. , если вы добавите новое поле в класс / интерфейс (или добавьте новый суперкласс / супер-интерфейс ), то статическое поле из суперинтерфейса клиентского класса C может скрыть добавленное поле (с тем же именем), унаследованное от суперкласса C (очень редкий случай).

Примечание. Существует множество других исключений, вызванных другими несовместимыми изменениями: NoSuchFieldError , NoSuchMethodError , IllegalAccessError , InstantiationError , VerifyError , NoClassDefFoundError и AbstractMethodError .

Лучшей статьей о BC является «Разработка API на основе Java 2: Достижение совместимости двоичных файлов API» , написанной Джим де Ривьер.

Существуют также некоторые автоматические инструменты для обнаружения таких изменений:

Использование japi-compliance-checker для вашей библиотеки:

japi-compliance-checker OLD.jar NEW.jar

Использование инструмента clirr:

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

Хорошо удачи!

90
ответ дан linuxbuild 26 August 2018 в 15:49
поделиться

Я столкнулся с этой проблемой, не разворачивая и передислоцируя войну со стеклянными рыбками. Моя структура класса была такой:

public interface A{
}

public class AImpl implements A{
}

, и она была изменена на

public abstract class A{
}

public class AImpl extends A{
}

. После остановки и перезапуска домена это получилось прекрасным. Я использовал стеклянную рыбку 3.1.43

1
ответ дан Nerrve 26 August 2018 в 15:49
поделиться

Я также обнаружил, что при использовании JNI, вызывая метод Java из C ++, если вы передадите параметры вызываемому Java-методу в неправильном порядке, вы получите эту ошибку при попытке использовать параметры внутри вызываемого метода (потому что они не будут подходящим типом). Сначала я был ошеломлен тем, что JNI не проверяет вас как часть проверки подписи класса при вызове метода, но я полагаю, что они не делают такого рода проверку, потому что вы можете передавать полиморфные параметры, и они должны предположим, что вы знаете, что делаете.

Пример 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.
}

Пример кода 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...
        }
    }
}
4
ответ дан Ogre Psalm33 26 August 2018 в 15:49
поделиться

Документирование другого сценария после сжигания слишком много времени.

Убедитесь, что у вас нет контейнера зависимости, который имеет класс с аннотацией EJB.

У нас был общий файл jar с аннотацией @local. Затем этот класс был перенесен из этого общего проекта и в наш основной проект jjb jar. Наш кувшин ejb и наша общая банка объединены в ухо. Версия нашей общей зависимости jar не обновлялась. Таким образом, 2 класса пытаются быть чем-то с несовместимыми изменениями.

0
ответ дан Snekse 26 August 2018 в 15:49
поделиться

Добавление моих 2 центов. Если вы используете scala и sbt и scala-logging как зависимость, тогда это может произойти из-за того, что ранняя версия scala-logging имела имя scala-logging-api.So; по существу, разрешения зависимостей не происходят из-за разных имен, приводящих к ошибкам во время запуска приложения scala.

0
ответ дан sourabh 26 August 2018 в 15:49
поделиться

Другая ситуация, когда эта ошибка может появиться, связана с обложкой кода Эмма.

Это происходит при назначении объекта интерфейсу. Я предполагаю, что это имеет какое-то отношение к объекту, инструментарий, а не бинарный совместимый.

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

К счастью, эта проблема не возникает с Cobertura, поэтому я добавил cobertura-maven-плагин в мои плагины отчетов моего pom.xml

1
ответ дан stivlo 26 August 2018 в 15:49
поделиться

Если это запись возможных случаев этой ошибки, то:

Я только что получил эту ошибку на WAS (8.5.0.1) во время загрузки весны CXF (2.6.0) (3.1 .1_release), где исключение BeanInstantiationException запустило исключение CXF ExtensionException, запустив IncompatibleClassChangeError. Следующий фрагмент показывает суть трассировки стека:

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

В этом случае решение заключалось в изменении порядка пути к модулю модуля в моем военном файле. То есть, откройте приложение войны в консоли WAS и выберите клиентский модуль (модули). В конфигурации модуля установите для класса-загрузки значение «parent last».

Это находится в консоли WAS:

  • Applicatoins -> Типы приложений -> WebSphere Enterprise Applications
  • Нажмите ссылку, представляющую ваше приложение (war)
  • Нажмите «Управление модулями» в разделе «Модули»
  • Нажмите ссылку для базового модуля (модулей)
  • Измените «Порядок загрузчика класса» равным «(родительский последний)».
0
ответ дан wmorrison365 26 August 2018 в 15:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: