Как исправить ошибку NoSuchMethodError?

178

Я получаю сообщение NoSuchMethodErrorоб ошибке при запуске моей Java-программы. Что не так и как мне это исправить?

Джон Мигер
источник
11
В Netbeans: щелкните правой кнопкой мыши по проекту на вкладке Projects, используйте «Очистить и построить». Решил это для меня.
Хайнцльмаен,
3
Также в Intellij Idea, rebuild иногда решает проблему
Hawk
1
Эта статья очень полезна для этого вопроса reflectoring.io/nosuchmethod
Michael Smith

Ответы:

228

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

Посмотрите на трассировку стека ... Если исключение появляется при вызове метода для объекта в библиотеке, вы, скорее всего, используете отдельные версии библиотеки при компиляции и запуске. Убедитесь, что у вас есть правильная версия в обоих местах.

Если исключение появляется при вызове метода для объектов, созданных созданными вами классами , то процесс сборки кажется неисправным. Убедитесь, что файлы классов, которые вы фактически используете, обновляются при компиляции.

Vetle
источник
3
Недавно мы обнаружили причину одного из них, и оказалось, что процесс сборки помещал файлы классов на место до выключения Java-сервера, и мы столкнулись с этим, потому что сервер Java не загрузил некоторые классы, а затем он загрузил некоторые, но получили эти новые, и так как новый код ссылался на методы, которых у старых классов не было ... bingo, NoSuchMethodError
vazor
«Посмотрите на трассировку стека ...» - Ну, я почти всегда иду и проверяю последний Caused byраздел в трассировке стека, чтобы найти класс виновника / jar
KrishPrabakar
108

У меня была твоя проблема, и вот как я ее исправил. Следующие шаги являются рабочим способом добавления библиотеки. Первые два шага я сделал правильно, но последний шаг я не сделал, перетащив файл «.jar» прямо из файловой системы в папку «lib» в моем проекте eclipse. Кроме того, мне пришлось удалить предыдущую версию библиотеки как из пути сборки, так и из папки "lib".

Шаг 1 - Добавьте .jar для построения пути

введите описание изображения здесь

Шаг 2 - Связать источники и javadocs (необязательно)

введите описание изображения здесь

Шаг 3 - На самом деле перетащите файл .jar в папку «lib» (не обязательно)

введите описание изображения здесь

Крис Датроу
источник
75
+1 за «Все ожидают, что вы знаете, как им пользоваться, а если нет, они понизят ваш вопрос».
Викрам
73

Обратите внимание, что в случае отражения вы получаете NoSuchMethodException, а с неотражающим кодом - NoSuchMethodError. Я склонен искать в очень разных местах, когда сталкиваюсь с одним против другого.

Эриксон
источник
Другими словами, вы говорите, что если вы используете отражение для получения метода в классе, а метод не найден, вы получаете исключение NoSuchMethodException. Но если вы находитесь в сценарии, когда вы компилируете свой код для некоторых библиотек, и на сервере у вас есть другие библиотеки (возможно, более новые, возможно, более старые), тогда вы получите NoSuchMethodError. Поправьте меня если я ошибаюсь.
Виктор
Это верно, @Victor
KrishPrabakar
51

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

java -verbose:class <other args>

Когда ваша программа запущена, JVM должна вывести на стандартную информацию, такую ​​как:

...

[Загружено junit.framework.Assert из файла: / C: /Program%20Files/junit3.8.2/junit.jar]

...

Мэтт Б
источник
3
+1 Гениально! Я решил неприятную небольшую проблему с помощью этого метода, спасибо. Это отличный способ узнать, когда классы каким-то образом проникли на путь к классам.
Дункан Джонс
1
+1 Ты спас мой день! Это была всего лишь одна библиотека, которая включала в свои источники старые классы с такими же именами.
Андрей Немченко
12

Это обычно вызывается при использовании системы сборки, такой как Apache Ant, которая компилирует файлы Java только тогда, когда файл Java новее, чем файл класса. Если сигнатура метода изменяется и классы используют старую версию, вещи могут быть скомпилированы неправильно. Обычное исправление - полная перестройка (обычно "ant clean", затем "ant").

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

Джон Мигер
источник
1
На самом деле, это больше похоже на проблему, которая возникает для программистов Java, которые используют любую среду разработки Java: Maven, NetBeans и Apache Ant, как вы можете видеть из всех ответов здесь.
HoldOffHunger
8

Если вы используете Maven или другой фреймворк, и вы получаете эту ошибку почти случайно, попробуйте чистую установку, например ...

clean install

Это особенно вероятно, если вы написали объект и знаете, что у него есть метод. Работал на меня.

HoldOffHunger
источник
Это также относится и к сборкам Gradle.
Джонатан
4

Это также может быть результатом использования отражения. Если у вас есть код, который отражает класс и извлекает метод по имени (например: with Class.getDeclaredMethod("someMethodName", .....)), то каждый раз, когда имя этого метода изменяется, например, во время рефакторинга, вам нужно будет помнить об обновлении параметров в методе отражения, чтобы они соответствовали подпись нового метода, или getDeclaredMethodвызов вызовет NoSuchMethodException.

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

По моему опыту, это иногда встречается при модульном тестировании частных методов / полей и использовании TestUtilitiesкласса для извлечения полей для проверки теста. (Как правило, с устаревшим кодом, который не был разработан с учетом модульного тестирования.)

rcreswick
источник
3

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

например

  • кот / общие / Lib
  • mywebapp / WEB-INF / Библиотека
Cheekysoft
источник
2

Эти проблемы вызваны использованием одного и того же объекта в тех же двух классах. Используемые объекты не содержат новый метод, который был добавлен в новый класс объектов.

например:

filenotnull=/DayMoreConfig.conf
16-07-2015 05:02:10:ussdgw-1: Open TCP/IP connection to SMSC: 10.149.96.66 at 2775
16-07-2015 05:02:10:ussdgw-1: Bind request: (bindreq: (pdu: 0 9 0 [1]) 900 900 GEN 52 (addrrang: 0 0 2000) ) 
Exception in thread "main" java.lang.NoSuchMethodError: gateway.smpp.PDUEventListener.<init>(Lgateway/smpp/USSDClient;)V
        at gateway.smpp.USSDClient.bind(USSDClient.java:139)
        at gateway.USSDGW.initSmppConnection(USSDGW.java:274)
        at gateway.USSDGW.<init>(USSDGW.java:184)
        at com.vinaphone.app.ttn.USSDDayMore.main(USSDDayMore.java:40)

-bash-3.00$ 

Эти проблемы вызваны сопутствующим 02 аналогичным классом (1 в src, 1 в jar-файле здесь - gateway.jar)

Quảng Trường Thời Đại
источник
2

Это означает, что соответствующий метод отсутствует в классе:

  1. Если вы используете jar, декомпилируйте и проверьте, имеет ли соответствующая версия jar соответствующий класс.
  2. Проверьте, правильно ли вы скомпилировали класс из вашего источника.
Shrikant
источник
2

Для меня это произошло потому, что я изменил тип аргумента в функции с Object a на String a. Я мог бы решить это с чистой и построить снова

Тито
источник
2

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

Райан Ло Сюй
источник
2

Попробуйте так: удалите все файлы .class из каталогов вашего проекта (и, конечно, все подкаталоги). Перестроить.

Иногда mvn clean(если вы используете maven) не очищает .class файлы, созданные вручную javac. И эти старые файлы содержат старые подписи, ведущие к NoSuchMethodError.

WHOIF
источник
2

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

  1. Очистили и построили проект в eclpise

  2. mvn clean install

  3. Перезапущенный кот

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

Code_Mode
источник
1

Чтобы ответить на оригинальный вопрос. Согласно документам Java здесь :

«NoSuchMethodError» Брошенный, если приложение пытается вызвать указанный метод класса (статический или экземпляр), и у этого класса больше нет определения этого метода.

Обычно эта ошибка отлавливается компилятором; эта ошибка может возникнуть только во время выполнения, если определение класса несовместимо изменилось.

  1. Если это происходит во время выполнения, проверьте, что класс, содержащий метод, находится в пути к классам.
  2. Проверьте, добавили ли вы новую версию JAR и совместим ли метод.
Reachgoals
источник
1

Я исправил эту проблему в Eclipse, переименовав тестовый файл Junit.
В моем рабочем пространстве Eclipse у меня есть проект App и тестовый проект.
Тестовый проект имеет проект App как необходимый проект на пути сборки.

Начал получать NoSuchMethodError.
Затем я понял, что класс в проекте Test имеет то же имя, что и класс в проекте App.

App/  
  src/
     com.example/  
       Projection.java
Test/  
  src/
     com.example/
       Projection.java

После переименования теста на правильное имя «ProjectionTest.java» исключение исчезло.

Дейв Инлоу
источник
У меня была похожая проблема. У меня был класс зависимости с таким же полным каноническим именем. После переименования исключение ушло.
moralejaSinCuentoNiProverbio
1

У меня была такая же ошибка:

  Exception in thread "main" java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonGenerator.writeStartObject(Ljava/lang/Object;)V
        at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:151)
        at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292)
        at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3681)
        at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3057)

Чтобы решить эту проблему, я сначала проверил диаграмму зависимостей модуля ( click in your POM the combination -> Ctrl+Alt+Shift+Uили right click in your POM -> Maven -> Show dependencies), чтобы понять, где именно был конфликт между библиотеками (Intelij IDEA). В моем конкретном случае у меня были разные версии зависимостей Джексона.

введите описание изображения здесь введите описание изображения здесь

1) Итак, я прямо добавил в свой POM проекта самую высокую версию - 2.8.7 из этих двух.

В свойствах:

<jackson.version>2.8.7</jackson.version>

И как зависимость:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
</dependency>

2) Но также это может быть решено с помощью исключения зависимостей .

По тому же принципу, что и в примере ниже:

  <dependency>
      <groupId>group-a</groupId>
      <artifactId>artifact-a</artifactId>
      <version>1.0</version>
          <exclusions>
             <exclusion>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
             </exclusion>
         </exclusions>
  </dependency>

Зависимость от нежелательной версии будет исключена из вашего проекта.

invzbl3
источник
1

В моем случае у меня был многомодульный проект, и сценарий был как com.xyz.TestClassв модуле, Aтак и в модуле, Bа модуль Aзависел от модуля B. Поэтому при создании jar-сборки я думаю, что была сохранена только одна версия класса, если у нее нет вызванного метода, тогда я получал NoSuchMethodErrorисключение времени выполнения, но компиляция прошла хорошо.

Связанный: https://reflectoring.io/nosuchmethod/

Гаурав Харе
источник
0

Я столкнулся с подобной проблемой, когда менял сигнатуры методов в своем приложении. Очистка и перестройка моего проекта решили "NoSuchMethodError".

knorman
источник
0

Приведенный выше ответ очень хорошо объясняет. Просто добавьте одну вещь. Если вы используете eclipse, используйте ctrl + shift + T и введите структуру пакета класса (например, gateway.smpp.PDUEventListener), вы найдете все jar / проекты, в которых он присутствует. , Удалите ненужные фляги из пути к классам или добавьте выше в пути к классам. Теперь он подберет правильный.

принц
источник
0

Я столкнулся с подобной проблемой.

Caused by: java.lang.NoSuchMethodError: com.abc.Employee.getEmpId()I

Наконец, я определил основную причину изменения типа данных переменной.

  1. Employee.java-> Содержит переменную ( EmpId), тип данных которой был изменен с intна String.
  2. ReportGeneration.java-> Получает значение , используя геттер, getEmpId().

Мы должны восстановить банку, включив только модифицированные классы. Поскольку изменений ReportGeneration.javaне было, я включил только Employee.classфайл Jar. Мне пришлось включить ReportGeneration.classфайл в банку, чтобы решить проблему.

AnonymousCoder
источник
0

У меня была такая же проблема. Это также вызвано тем, что в классах есть неоднозначность. Моя программа пыталась вызвать метод, который присутствовал в двух файлах JAR, находящихся в одном и том же месте / пути к классам. Удалите один файл JAR или выполните свой код так, чтобы использовался только один файл JAR. Убедитесь, что вы не используете один и тот же JAR или разные версии одного и того же JAR, которые содержат один и тот же класс.

DISP_E_EXCEPTION [шаг] [] [Z-JAVA-105 Java-исключение java.lang.NoSuchMethodError (com.example.yourmethod)]

ShankarDaruga
источник
0

В большинстве случаев java.lang.NoSuchMethodError перехватывается компилятором, но иногда это может происходить во время выполнения. Если эта ошибка возникает во время выполнения, единственной причиной может быть изменение в структуре класса, которое сделало ее несовместимой.

Лучшее объяснение: https://www.journaldev.com/14538/java-lang-nosuchmethoderror

Яш П Шах
источник
0

Я тоже столкнулся с этой ошибкой.

Моя проблема заключалась в том, что я изменил подпись метода, что-то вроде

void invest(Currency money){...}

в

void invest(Euro money){...}

Этот метод был вызван из контекста, аналогичного

public static void main(String args[]) {
    Bank myBank = new Bank();

    Euro capital = new Euro();
    myBank.invest(capital);
}

Компилятор молчал в отношении предупреждений / ошибок, поскольку капитал - это как валюта, так и евро.

Проблема возникла из-за того, что я скомпилировал только класс, в котором был определен метод - Bank, но не класс, из которого вызывается метод, который содержит метод main ().

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

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

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

Исходный дизассемблированный байт-код (сгенерированный с помощью инструмента javap) выглядит следующим образом:

 #7 = Methodref          #2.#22         // Bank.invest:(LCurrency;)V

После того, как ClassLoader загрузит новый скомпилированный Bank.class, он не найдет такой метод, он выглядит так, как если бы он был удален и не изменен, то есть названная ошибка.

Надеюсь это поможет.

Михай Савин
источник
0

Проблема в моем случае заключалась в том, что в пути сборки было две версии одной и той же библиотеки. В старой версии библиотеки не было этой функции, а в более новой.

KK
источник
0

У меня была похожая проблема с моим Gradle Project, использующим Intelij. Я решил это, удалив пакет .gradle (см. Скриншот ниже) и перестроив проект. Пакет

J.Orlando
источник
0

NoSuchMethodError: Я потратил пару часов на исправление этой проблемы, наконец исправил ее, просто переименовав имя пакета, очистив и собрав ... Сначала попробуйте очистить сборку, если она не работает, попробуйте переименовать имя класса или имя пакета и очистить сборку. .это должно быть исправлено. Удачи.

Шириш Сингх
источник
-2

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

Амит Уолк
источник