Java получает NoSuchMethodError из-за нескольких зависимостей [дубликат]JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Гость
 Java получает NoSuchMethodError из-за нескольких зависимостей [дубликат]

Сообщение Гость »


Я использую gitlab4j стороннего производителя (пробовал версию 5.0.1, а также 5.3.0), который использует внутренний jersey-client (версии 2.35 и 2.39.1 соответственно) ). Я получаю NoSuchMethodError из кода jersey-client.

Мне удалось создать аналогичный небольшой проект (Github), имитирующий мой код. установка с теми же версиями jar (проверено вместе со всеми транзитивными зависимостями), скомпилировано с тем же плагином компилятора maven (3.1), работает с той же версией Java (11.0.20), выполняется с теми же файлами jar в пути к классам, что и в моем основном проекте --> и в этом проекте код работает хорошо и не дает сбоев.

Это настройка соответствующих классов:

Интерфейс MultivaluedMap содержит метод void addAll(K key, V... newValues). во время выполнения создается экземпляр StringKeyIgnoreCaseMultivaluedMap (это означает, что K — это String, а V — это Объект)

Этот фрагмент кода вызвал ошибку:

public void Accept (окончательные типы String...) { getHeaders().addAll(HttpHeaders.ACCEPT, (Object[]) типы); } getHeaders возвращает экземпляр в интерфейсе MultivaluedMap. Фактический код addAll находится в классе, объявленном как AbstractMultivaluedMap (это экземпляр приведенного выше StringKeyIgnoreCaseMultivaluedMap, который расширяет AbstractMultivaluedMap).

Я получаю сообщение об ошибке:

Вызвано: java.lang.NoSuchMethodError: javax.ws.rs.core.MultivaluedMap.addAll(Ljava/lang/Object;[Ljava/lang/Object;)V в org.glassfish.jersey.client.ClientRequest.accept(ClientRequest.java:280) в org.glassfish.jersey.client.JerseyInvocation$Builder.accept(JerseyInvocate.java:242) в org.glassfish.jersey.client.JerseyInvocation$Builder.accept(JerseyInvocate.java:165) ... Еще раз: этот код хорошо работает в моем примере небольшого проекта и дает сбой только в моем основном проекте.

ОБНОВЛЕНИЕ:

Отвечаю здесь на свой вопрос, поскольку «боги ТАК» закрыли мой вопрос несколько часов назад.. :( Я думаю, что случай, с которым я столкнулся, интересен и о нем стоит узнать другим.

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

Наша основная причина в конечном итоге была связана с тем фактом, что у нас было два jar-файла с одинаковым объявлением интерфейса (согласно его FQN), и во время выполнения он работал с интерфейсом, в котором отсутствовало объявление метода -> метод addAll

Интерфейс javax.ws.rs.core.MultivaluedMap был объявлен в двух jar-файлах внутри моего проекта: jsr311-api-1.1.jar (я буду ссылаться на него как JSR), а также в jakarta.ws.rs-api-2.1.6.jar (jakarta)

В версии JSR не было вышеупомянутого метода addAll; версия для Джакарты содержала все методы, которые были в JSR, плюс метод addAll.

Экземпляр класса, используемый как во время компиляции, так и во время выполнения, реализует версию Jakarta и имеет реализацию метода addAll (StringKeyIgnoreCaseMultivaluedMap). Но при вызове на него ссылаются через имя интерфейса (MultivaluedMap), и тут у нас возникла ошибка: версия интерфейса, обнаруженная во время выполнения, исходит из JSR, а нет удерживайте объявление метода addAll.

Для меня это более интересный случай (и мне интересно, может ли кто-нибудь поделиться и объяснить его, если сталкивался с этим в прошлом):

Обычно случаи NoSuchMethodError связаны с наличием класса во время компиляции, который имеет метод X, а во время выполнения загружается другая версия класса, не имеющая метода X. (по крайней мере, те случаи, которые я столкнулся и прочитал)

Здесь ситуация немного другая: фактический экземпляр класса имеет реализацию этого метода (в байт-коде), но только потому, что на него ссылались через (неправильный) интерфейс, который не имеет этого метода - Ошибка была вызвана.

У меня создалось впечатление, что единственное, что имеет значение во время выполнения, — это фактический экземпляр, но теперь поведение показывает, что именно его ссылочный тип является тем, который устанавливает вызовы.
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»