Я упаковываю библиотеку Java как JAR, и она выдает много java.lang.IncompatibleClassChangeError
s, когда я пытаюсь вызвать из нее методы. Эти ошибки кажутся случайными. Какие проблемы могут быть причиной этой ошибки?
java
jar
runtime-error
binary-compatibility
Zombies
источник
источник
Ответы:
Это означает, что вы внесли некоторые несовместимые двоичные изменения в библиотеку, не перекомпилировав код клиента. Спецификация языка Java § 13 подробно описывает все такие изменения, в первую очередь, изменение не-
static
не приватных полей / методов наstatic
или наоборот.Перекомпилируйте клиентский код с новой библиотекой, и вы должны быть в порядке.
ОБНОВЛЕНИЕ: Если вы публикуете публичную библиотеку, вам следует избегать как можно большего количества несовместимых двоичных изменений, чтобы сохранить так называемую «двоичную обратную совместимость». Обновление банок зависимостей в идеале не должно нарушать работу приложения или сборки. Если вам необходимо нарушить двоичную обратную совместимость, рекомендуется увеличить номер основной версии (например, с 1.xy до 2.0.0) перед тем, как отменить изменение.
источник
*.class
файлы) и перекомпилировать? Редактирование файлов имеет аналогичный эффект.Ваша недавно упакованная библиотека не имеет обратной совместимости с двоичными файлами (BC) со старой версией. По этой причине некоторые из библиотечных клиентов, которые не перекомпилированы, могут выдать исключение.
Это полный список изменений в API библиотеки Java, которые могут привести к тому, что клиенты, созданные со старой версией библиотеки, сгенерируют java.lang. IncompatibleClassChangeError, если они запускаются на новом (то есть, ломая BC):
Примечание . Существует множество других исключений, вызванных другими несовместимыми изменениями: NoSuchFieldError , NoSuchMethodError , IllegalAccessError , InstantiationError , VerifyError , NoClassDefFoundError и AbstractMethodError .
Лучшая статья о BC - «Развитие API на основе Java 2: достижение двоичной совместимости API», написанная Jim des Rivières.
Есть также несколько автоматических инструментов для обнаружения таких изменений:
Использование japi-Compliance-Checker для вашей библиотеки:
Использование инструмента Clirr:
Удачи!
источник
Хотя все эти ответы верны, решить проблему часто сложнее. Обычно это результат двух разных версий одной и той же зависимости от пути к классам, и почти всегда он вызван тем, что суперкласс отличается от того, который изначально был скомпилирован из-за того, что он находится в пути к классам, или некоторым изменением импорта транзитивного замыкания, но обычно в классе создание экземпляра и вызов конструктора. (После успешной загрузки класса и вызова ctor вы получите
NoSuchMethodException
или еще что-нибудь .)Если поведение кажется случайным, это, вероятно, результат многопоточной программы, загружающей различные транзитивные зависимости в зависимости от того, какой код был достигнут первым.
Чтобы устранить их, попробуйте запустить ВМ
-verbose
в качестве аргумента, а затем посмотрите на классы, которые загружались при возникновении исключения. Вы должны увидеть некоторую удивительную информацию. Например, наличие нескольких копий одной и той же зависимости и версий, которые вы никогда не ожидали или приняли бы, если бы знали, что они включены.Устранение дубликатов jar-файлов с помощью Maven лучше всего выполнить с помощью комбинации плагинов maven-dependency-plugin и maven-inspecer-plugin в Maven (или подключаемого модуля SBT Dependency Graph , с последующим добавлением этих jar-файлов в раздел POM верхнего уровня или в качестве импортированной зависимости). элементы в SBT (чтобы удалить эти зависимости).
Удачи!
источник
Я также обнаружил, что при использовании JNI, при вызове метода Java из C ++, если вы передадите параметры вызванному методу Java в неправильном порядке, вы получите эту ошибку, когда попытаетесь использовать параметры внутри вызываемого метода (потому что они не будет правильного типа). Сначала я был озадачен тем, что JNI не выполняет эту проверку для вас как часть проверки подписи класса, когда вы вызываете метод, но я предполагаю, что они не выполняют такую проверку, потому что вы можете передавать полиморфные параметры, и они должны Предположим, вы знаете, что делаете.
Пример C ++ JNI-кода:
Пример кода Java:
источник
У меня была та же проблема, и позже я понял, что я запускаю приложение на Java версии 1.4, в то время как приложение скомпилировано на версии 6.На самом деле причина была в том, что у нас была дублирующаяся библиотека: одна находится в пути к классам, а другая включена в файл JAR, расположенный в пути к классам.
источник
Еще одна ситуация, в которой может появиться эта ошибка, - Эмма-код Покрытие.
Это происходит при назначении объекта интерфейсу. Я предполагаю, что это как-то связано с инструментируемым объектом, который больше не является бинарно-совместимым.
http://sourceforge.net/tracker/?func=detail&aid=3178921&group_id=177969&atid=883351
К счастью, эта проблема не возникает с Cobertura, поэтому я добавил cobertura-maven-plugin в свои плагины для отчетов моего pom.xml
источник
Я столкнулся с этой проблемой при развертывании и развертывании войны со стеклянной рыбой. Моя классовая структура была такой,
и это было изменено на
После остановки и перезапуска домена все заработало нормально. Я использовал Glassfish 3.1.43
источник
У меня есть веб-приложение, которое прекрасно разворачивается на tomcat моей локальной машины (8.0.20). Однако, когда я поместил его в среду qa (tomcat - 8.0.20), он продолжал давать мне IncompatibleClassChangeError, и он жаловался, что я расширяю интерфейс. Этот интерфейс был изменен на абстрактный класс. И я скомпилировал родительские и дочерние классы, и все же продолжал получать ту же проблему. Наконец, я хотел отладить, поэтому я изменил версию на родительском для x.0.1-SNAPSHOT, а затем скомпилировал все, и теперь это работает. Если кто-то все еще сталкивается с проблемой после выполнения ответов, приведенных здесь, убедитесь, что версии в вашем файле pom.xml также верны. Измените версии, чтобы увидеть, работает ли это. Если так, то исправьте проблему с версией.
источник
Мой ответ, я полагаю, будет конкретным для Интеллидж.
Я восстановил чистый, даже зашел так далеко, что вручную удалил "out" и "target" dirs. Intellij имеет «аннулировать кэши и перезапустить», что иногда удаляет нечетные ошибки. На этот раз это не сработало. Все версии зависимостей выглядят корректно в меню «Настройки проекта» -> «Модули».
Окончательный ответ состоял в том, чтобы вручную удалить мою проблемную зависимость из моего локального репозитория Maven. Преступником была старая версия bouncycastle (я знал, что только что сменил версию, и это будет проблемой), и хотя старая версия не показала, где в том, что строится, она решила мою проблему. Я использовал Intellij версии 14, а затем обновился до 15 во время этого процесса.
источник
В моем случае я столкнулся с этой ошибкой таким образом.
pom.xml
моего проекта определены две зависимостиA
иB
. И какA
иB
определяется зависимость же артефакт (назовем егоC
) , но различные версии этого (C.1
иC.2
). Когда это происходит, для каждого класса вC
maven можно выбрать только одну версию класса из двух версий (при создании uber-jar ). Он выберет «ближайшую» версию на основе своих правил передачи зависимостей и выдаст предупреждение «У нас есть дублирующийся класс ...». Если сигнатура метода / класса изменяется между версиями, это может вызватьjava.lang.IncompatibleClassChangeError
исключение, если неверная версия используется во время выполнения.Дополнительно: если
A
необходимо использовать v1 ofC
иB
должно использовать v2 ofC
, то мы должны переместитьC
вA
иB
poms, чтобы избежать конфликта классов (у нас есть дублирующееся предупреждение о классе) при построении окончательного проекта, который зависит от обоихA
иB
.источник
В моем случае ошибка появилась, когда я добавил
com.nimbusds
библиотеку в мое приложение, на котором развернутоWebsphere 8.5
.Произошло следующее исключение:
Решением было исключить asm jar из библиотеки:
источник
Пожалуйста, проверьте, не состоит ли ваш код из двух проектов модулей с одинаковыми именами классов и определением пакетов. Например, это может произойти, если кто-то использует copy-paste для создания новой реализации интерфейса на основе предыдущей реализации.
источник
Если это запись о возможных случаях этой ошибки, то:
Я только что получил эту ошибку на WAS (8.5.0.1), во время загрузки CXF (2.6.0) конфигурации Spring (3.1.1_release), где BeanInstantiationException свернуло исключение CXF ExtensionException и свернуло IncompatibleClassChangeError. Следующий фрагмент кода показывает суть трассировки стека:
В этом случае решение состояло в том, чтобы изменить порядок пути к классу модуля в моем файле войны. То есть откройте приложение war в консоли WAS и выберите клиентские модули. В конфигурации модуля установите загрузку классов как «родительский последний».
Это находится в консоли WAS:
источник
Документирование другого сценария после прожигания слишком много времени.
Убедитесь, что у вас нет jar зависимостей, в котором есть класс с аннотацией EJB.
У нас был общий jar-файл с
@local
аннотацией. Позже этот класс был перенесен из этого общего проекта в наш основной проект ejb jar. Наш ejb jar и наш общий jar связаны в ухо. Версия нашей общей jar-зависимости не была обновлена. Таким образом 2 класса пытаются быть чем-то с несовместимыми изменениями.источник
Все вышеперечисленное - по какой-то причине я занимался большим рефакторингом и начинал это понимать. Я переименовал пакет, в котором был мой интерфейс, и это очистило его. Надеюсь, это поможет.
источник
По какой-то причине то же исключение также выдается при использовании JNI и передаче аргумента jclass вместо jobject при вызове
Call*Method()
.Это похоже на ответ из Огрского псалма 33.
Я знаю, что уже поздно отвечать на этот вопрос через 5 лет после того, как его спросили, но это один из главных хитов при поиске,
java.lang.IncompatibleClassChangeError
поэтому я хотел задокументировать этот особый случай.источник
Добавление моих 2 центов. Если вы используете scala и sbt и scala-logging в качестве зависимости, то это может произойти, потому что более ранняя версия scala-logging имела имя scala-logging-api.So; по сути, разрешения зависимостей не происходят из-за различных имена, приводящие к ошибкам во время выполнения приложения scala.
источник
Дополнительная причина этой проблемы - если вы
Instant Run
включили Android Studio.Исправление
Если вы обнаружите, что начинаете получать эту ошибку, выключите
Instant Run
.Зачем
Instant Run
изменяет большое количество вещей во время разработки, чтобы быстрее предоставлять обновления для вашего работающего приложения. Отсюда мгновенный бег. Когда это работает, это действительно полезно. Однако, когда возникает такая проблема, лучше всего отключить ееInstant Run
до следующей версии Android Studio.источник