Как исправить ошибку NoSuchMethodError?
Я получаю NoSuchMethodError
ошибка при запуске моей программы на Java. Что не так и как мне это исправить?
34 ответа
Без дополнительной информации трудно точно определить проблему, но основная причина заключается в том, что вы, скорее всего, скомпилировали класс для другой версии класса, в которой отсутствует метод, а не той, которую вы используете при его запуске.
Посмотрите на трассировку стека... Если исключение появляется при вызове метода для объекта в библиотеке, вы, скорее всего, используете отдельные версии библиотеки при компиляции и запуске. Убедитесь, что у вас есть правильная версия в обоих местах.
Если исключение появляется при вызове метода для объектов, созданных созданными вами классами, то процесс сборки кажется неисправным. Убедитесь, что файлы классов, которые вы на самом деле используете, обновляются при компиляции.
У меня была твоя проблема, и вот как я ее исправил. Следующие шаги являются рабочим способом добавления библиотеки. Первые два шага я выполнил правильно, но последний шаг я не выполнил, перетащив файл ".jar" непосредственно из файловой системы в папку "lib" в моем проекте eclipse. Кроме того, мне пришлось удалить предыдущую версию библиотеки как из пути сборки, так и из папки "lib".
Шаг 1 - Добавьте.jar для построения пути
Шаг 2 - Связать источники и javadocs (необязательно)
Шаг 3 - На самом деле перетащите файл.jar в папку "lib" (не обязательно)
Обратите внимание, что в случае отражения вы получите NoSuchMethodException
в то время как с неотражающим кодом вы получаете NoSuchMethodError
, Я склонен искать в очень разных местах, когда сталкиваюсь с одним против другого.
Если у вас есть доступ к изменению параметров JVM, добавление подробного вывода должно позволить вам увидеть, какие классы загружаются из каких JAR-файлов.
java -verbose:class <other args>
Когда ваша программа запущена, JVM должна вывести на стандартную информацию, такую как:
...
[Загружено junit.framework.Assert из файла: / C: /Program%20Files/junit3.8.2/junit.jar]
...
Если вы используете maven или другой фреймворк, и вы получаете эту ошибку почти случайно, попробуйте "чистую установку", особенно если вы написали объект и знаете, что у него есть метод. Работал на меня.
Это обычно вызывается при использовании системы сборки, такой как Apache Ant, которая компилирует java-файлы, только когда java-файл новее, чем файл класса. Если сигнатура метода изменяется и классы используют старую версию, вещи могут быть скомпилированы неправильно. Обычное исправление - сделать полную перестройку (обычно "ant clean", затем "ant").
Иногда это также может быть вызвано при компиляции с одной версией библиотеки, но с другой версией.
У меня была такая же ошибка:
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>
Зависимость от нежелательной версии будет исключена из вашего проекта.
Почему никто не упоминает о конфликтах зависимостей? Эта общая проблема может быть связана с включенными jar-файлами зависимостей с разными версиями. Подробное объяснение и решение: https://dzone.com/articles/solving-dependency-conflicts-in-maven
Краткий ответ;
Добавьте эту зависимость maven;
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<rules>
<dependencyConvergence />
</rules>
</configuration>
</plugin>
Затем запустите эту команду;
mvn enforcer:enforce
Возможно, это причина вашей проблемы, с которой вы столкнулись.
Если вы пишете веб-приложение, убедитесь, что у вас нет конфликтующих версий jar-файла в каталоге глобальной библиотеки вашего контейнера, а также в вашем приложении. Вы можете не обязательно знать, какой jar-файл используется загрузчиком классов.
например
- кот / общий / Lib
- mywebapp / WEB-INF / Библиотека
Для меня это произошло потому, что я изменил тип аргумента в функции с Object a на String a. Я мог бы решить это с чистой и построить снова
Это также может быть результатом использования отражения. Если у вас есть код, который отражает класс и извлекает метод по имени (например: с Class.getDeclaredMethod("someMethodName", .....)
) затем каждый раз, когда имя этого метода изменяется, например, во время рефакторинга, вам нужно будет не забывать обновлять параметры метода отражения, чтобы соответствовать сигнатуре нового метода, или getDeclaredMethod
вызов бросит NoSuchMethodException
,
Если это причина, то трассировка стека должна показывать точку, в которой вызывается метод отражения, и вам просто нужно обновить параметры, чтобы они соответствовали фактической сигнатуре метода.
По моему опыту, это иногда возникает, когда юнит тестирует частные методы / поля и использует TestUtilities
класс для извлечения полей для проверки теста. (Как правило, с устаревшим кодом, который не был разработан с учетом модульного тестирования.)
В моем случае у меня был многомодульный проект, и сценарий был похож на com.xyz.TestClass
был в модуле A
а также в модуле B
и модуль A
зависел от модуля B
. Поэтому при создании сборочной банки я думаю, что была сохранена только одна версия класса, если у нее нет вызванного метода, тогда я получалNoSuchMethodError
исключение времени выполнения, но компиляция прошла нормально.
Попробуйте так: удалите все файлы.class из каталогов вашего проекта (и, конечно, все подкаталоги). Перестроить.
Иногда mvn clean
(если вы используете maven) не очищает.class файлы, созданные вручную javac
, И эти старые файлы содержат старые подписи, ведущие к NoSuchMethodError
,
Это означает, что соответствующий метод отсутствует в классе:
- Если вы используете jar, декомпилируйте и проверьте, имеет ли соответствующая версия jar соответствующий класс.
- Проверьте, правильно ли вы скомпилировали класс из вашего источника.
Я только что решил эту ошибку, перезапустив Eclipse и запустив приложение. Причиной моего дела может быть то, что я заменяю свои исходные файлы, не закрывая свой проект или Eclipse. Что вызвало разные версии классов, которые я использовал.
Просто добавляю к существующим ответам. Я столкнулся с этой проблемой с котом в затмении. Я изменил один класс и сделал следующие шаги,
Очистили и построили проект в eclpise
mvn clean install
- Перезапущенный кот
Тем не менее я столкнулся с той же ошибкой. Затем я очистил tomcat, очистил рабочий каталог tomcat и перезапустил сервер, и моя проблема исчезла. Надеюсь, это поможет кому-то
Я исправил эту проблему в Eclipse, переименовав тестовый файл Junit.
В моем рабочем пространстве Eclipse у меня есть проект App и тестовый проект.
Тестовый проект имеет проект App в качестве обязательного проекта на пути сборки.
Начал получать NoSuchMethodError.
Затем я понял, что класс в проекте Test имеет то же имя, что и класс в проекте App.
App/
src/
com.example/
Projection.java
Test/
src/
com.example/
Projection.java
После переименования теста на правильное имя "ProjectionTest.java" исключение исчезло.
Эти проблемы вызваны использованием одного и того же объекта в тех же двух классах. Используемые объекты не содержат новый метод, который был добавлен в новый класс объектов.
например:
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)
Чтобы ответить на оригинальный вопрос. Согласно документам Java здесь:
"NoSuchMethodError" Брошенный, если приложение пытается вызвать определенный метод класса (статический или экземпляр), и у этого класса больше нет определения этого метода.
Обычно эта ошибка отлавливается компилятором; эта ошибка может возникнуть только во время выполнения, если определение класса несовместимо изменилось.
- Если это происходит во время выполнения, проверьте, что класс, содержащий метод, находится в пути к классам.
- Проверьте, добавили ли вы новую версию JAR и совместим ли метод.
NoSuchMethodError: Я потратил пару часов на исправление этой проблемы, наконец исправил ее, просто переименовав имя пакета, очистив и собрав... Сначала попробуйте очистить сборку, если она не работает, попробуйте переименовать имя класса или имя пакета и очистить сборку..это должно быть исправлено. Удачи.
Я тоже столкнулся с этой ошибкой.
Моя проблема заключалась в том, что я изменил подпись метода, что-то вроде
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().
С этой проблемой вы можете столкнуться не слишком часто, так как чаще всего проект перестраивается вручную или действие Build запускается автоматически, а не просто компилирует один измененный класс.
Мой вариант использования состоял в том, что я сгенерировал файл.jar, который должен был использоваться в качестве исправления, который не содержал класс App.class, поскольку он не был изменен. Для меня имело смысл не включать его, так как я сохранил базовый класс с помощью наследования базового класса.
Дело в том, что когда вы компилируете класс, результирующий байт-код является статическим, иными словами, это жесткая ссылка.
Исходный дизассемблированный байт-код (созданный с помощью инструмента javap) выглядит следующим образом:
#7 = Methodref #2.#22 // Bank.invest:(LCurrency;)V
После того, как ClassLoader загрузит новый скомпилированный Bank.class, он не найдет такой метод, он выглядит так, как если бы он был удален и не изменен, то есть названная ошибка.
Надеюсь это поможет.
Я столкнулся с подобной проблемой, когда менял сигнатуры методов в своем приложении. Очистка и перестройка моего проекта решили "NoSuchMethodError".
Приведенный выше ответ очень хорошо объясняет. Просто добавьте одну вещь. Если вы используете eclipse, используйте ctrl+shift+T и введите структуру пакета класса (например, gateway.smpp.PDUEventListener), вы найдете все jar / проекты, в которых он присутствует., Удалите ненужные фляги из пути к классам или добавьте выше в пути к классам. Теперь он подберет правильный.
У меня была такая же проблема. Это также вызвано тем, что в классах есть неоднозначность. Моя программа пыталась вызвать метод, который присутствовал в двух файлах JAR, находящихся в одном и том же месте / пути к классам. Удалите один файл JAR или выполните свой код так, чтобы использовался только один файл JAR. Убедитесь, что вы не используете один и тот же JAR или разные версии одного и того же JAR, которые содержат один и тот же класс.
DISP_E_EXCEPTION [шаг] [] [Z-JAVA-105 Java-исключение java.lang.NoSuchMethodError(com.example.yourmethod)]
В большинстве случаев java.lang.NoSuchMethodError перехватывается компилятором, но иногда это может происходить во время выполнения. Если эта ошибка возникает во время выполнения, то единственной причиной может быть изменение структуры класса, которое сделало ее несовместимой.
Лучшее объяснение: https://www.journaldev.com/14538/java-lang-nosuchmethoderror
Проблема в моем случае заключалась в наличии двух версий одной и той же библиотеки в пути сборки. В старой версии библиотеки не было этой функции, а в более новой.
У меня была похожая проблема с моим Gradle Project, использующим Intelij. Я решил это, удалив пакет.gradle (см. Скриншот ниже) и перестроив проект. Пакет
Я столкнулся с подобной проблемой.
Caused by: java.lang.NoSuchMethodError: com.abc.Employee.getEmpId()I
Наконец, я определил причину изменения типа данных переменной.
Employee.java
-> Содержит переменную (EmpId
) тип данных которого был изменен сint
вString
,ReportGeneration.java
-> Получает значение, используя геттер,getEmpId()
,
Мы должны восстановить банку, включив только модифицированные классы. Как не было никаких изменений в ReportGeneration.java
Я был только в том числе Employee.class
в фляге Я должен был включить ReportGeneration.class
файл в банке, чтобы решить проблему.
Я столкнулся с той же проблемой. Я изменил тип возврата одного метода и запустил тестовый код этого одного класса. Вот когда я столкнулся с этим
NoSuchMethodError
. В качестве решения я один раз запустил сборки maven для всего репозитория, прежде чем снова запустить тестовый код. Проблема была решена в следующем одиночном тестовом запуске.
Я решил проблему при использовании Quarkus, удалив целевую папку и перезапустив программу.