Як виправити NoSuchMethodError?


178

Я отримую NoSuchMethodErrorпомилку під час запуску програми Java. Що не так і як це виправити?


11
У Netbeans: Клацніть правою кнопкою миші на проект на вкладці Проекти, використовуйте «Очистити та побудувати». Вирішили це для мене.
Хайнцльман

3
Також в Intellij Idea перебудова вирішує проблему іноді
Хоук

1
Ця стаття дуже корисна для цього питання reflectoring.io/nosuchmethod
Майкл Сміт

Відповіді:


228

Без додаткової інформації важко визначити проблему, але першопричиною є те, що ви, швидше за все, склали клас проти іншої версії класу, у якій відсутній метод, ніж тієї, яку ви використовуєте під час її запуску.

Подивіться на стек стека ... Якщо виняток з’являється при виклику методу на об’єкт у бібліотеці, ви, швидше за все, використовуєте окремі версії бібліотеки при компілюванні та запуску. Переконайтеся, що у вас є правильна версія обох місць.

Якщо виняток з’являється під час виклику методу на об'єктах, створених за допомогою створених вами класів , то ваш процес збирання здається помилковим. Переконайтесь, що файли класу, які ви фактично запущені, оновлюються при компіляції.


3
Нещодавно ми виявили причину однієї з них, і виявилося, що процес збирання ставив файли класів на місце до того, як java-сервер був закритий, і ми вдарили це, тому що сервер Java не завантажив деякі класи, а потім він завантажився Деякі, але вони отримали ці нові, і оскільки новий код посилався на методи, яких у старих класах не було ... bingo, NoSuchMethodError
vazor

"Подивіться на стек стека ..." - Ну, я майже завжди заходжу і перевіряю останній Caused byрозділ у сліді стека, щоб знайти клас винуватця / банку
KrishPrabakar

108

У мене виникли ваші проблеми, і це я вирішив. Наступні кроки - це робочий спосіб додати бібліотеку. Перші два кроки я зробив правильно, але останнього не зробив, перетягнувши файл ".jar" безпосередньо з файлової системи в папку "lib" мого проекту затемнення. Крім того, мені довелося видалити попередню версію бібліотеки як із шляху збірки, так і з папки "lib".

Крок 1 - Додайте .jar для створення контуру

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

Крок 2 - Пов’язані джерела та javadocs (необов’язково)

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

Крок 3 - Фактично перетягніть .jar файл у папку "lib" (не обов’язково)

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


75
+1 за "Усі очікують, що ви знаєте, як ним користуватися, і якщо ви цього не зробите, вони не сприймають ваше запитання".
Вікрам

73

Зауважте, що у випадку рефлексії ви отримуєте NoSuchMethodException, тоді як при невідбиваючому коді ви отримуєте NoSuchMethodError. Я схильний шукати в дуже різних місцях, коли стикаюся з одним проти іншого.


Іншими словами, ви говорите, що якщо ви використовуєте відображення для отримання методу на класі, а метод не знайдений, ви отримаєте NoSuchMethodException. Але якщо у вас є сценарій, коли ви компілювали свій код проти деяких libs, а на сервері у вас є інші lib (можливо новіші, можливо, старші), ви отримуєте NoSuchMethodError. Виправте мене, якщо я помиляюся.
Віктор

Це правильно, @Victor
KrishPrabakar

51

Якщо у вас є доступ до зміни параметрів JVM, додавання багатослівного виводу повинно дозволяти вам бачити, які класи завантажуються, з яких файлів JAR.

java -verbose:class <other args>

Коли ваша програма запускається, JVM повинен скинутись на стандартну інформацію, таку як:

...

[Завантажений junit.framework.Введіть файл: / C: /Program%20Files/junit3.8.2/junit.jar]

...


3
+1 Блискуче! Я вирішив неприємну маленьку проблему, використовуючи цей метод, дякую. Це прекрасний спосіб виявити, коли заняття проникли на шлях класу.
Данкан Джонс

1
+1 Ти врятував мені день! Це була лише одна бібліотека, яка включала в свої джерела старі класи з однаковими назвами.
Андрій Немченко

12

Зазвичай це виникає при використанні системи збирання типу Apache Ant, яка компілює файли java лише тоді, коли файл java новіший, ніж файл класу. Якщо зміни підпису методу та класи використовували стару версію, речі можуть бути складені неправильно. Звичайний виправлення - зробити повну перебудову (як правило, "мураха чистий", а потім "мураха").

Іноді це також може бути викликано при компіляції проти однієї версії бібліотеки, але працює проти іншої версії.


1
Насправді це більше схоже на проблему, яка виникає для програмістів Java, які використовують будь-які рамки розробки Java: Maven, NetBeans та Apache Ant, як видно з усіх відповідей тут.
HoldOffHunger

8

Якщо ви використовуєте Maven або інший фреймворк, і ви отримуєте цю помилку майже випадковим чином, спробуйте чисту установку, як ...

clean install

Особливо ймовірно, що це спрацює, якщо ви написали об'єкт і знаєте, що він має метод. Працювали для мене.


Це також стосується побудови Gradle.
Джонатан

4

Це також може бути результатом використання рефлексії. Якщо у вас є код, який відображає клас і витягує метод за назвою (наприклад: з Class.getDeclaredMethod("someMethodName", .....)), то кожного разу, коли ім'я цього методу змінюється, наприклад, під час рефактора, вам потрібно буде пам’ятати, щоб оновити параметри до методу відображення, щоб відповідати відповідності новий метод підпису, або getDeclaredMethodвиклик буде кидати a NoSuchMethodException.

Якщо це причина, то слід стека повинен показувати точку, що викликається метод відображення, і вам просто потрібно буде оновити параметри, щоб відповідати фактичному підпису методу.

На мій досвід, це трапляється періодично, коли тестування одиничних методів / полів використовується і TestUtilitiesдля вилучення полів для перевірки тесту. (Як правило, із застарілим кодом, який не розроблявся з урахуванням тестування одиниць.)


3

Якщо ви пишете веб-сторінку, переконайтеся, що у вас немає суперечливих версій банку в глобальній каталозі бібліотеки вашого контейнера, а також у вашому додатку. Можливо, ви не обов'язково знаєте, яку банку використовує завантажувач.

напр

  • tomcat / звичайний / lib
  • mywebapp / WEB-INF / lib

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)


2

Це означає, що відповідний метод не присутній у класі:

  1. Якщо ви використовуєте jar, тоді декомпілюйте та перевірте, чи є у відповідної версії jar належний клас.
  2. Перевірте, чи склали ви власний клас зі свого джерела.

2

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


2

Я щойно вирішив цю помилку, перезапустивши Eclipse і запустивши додаток. Причина моєї справи може полягати в тому, що я замінюю свої вихідні файли, не закриваючи проект або Eclipse. Що спричинило різну версію класів, якими я користувався.


2

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

Іноді mvn clean(якщо ви використовуєте maven) не очищає файли .class, створені вручну javac. І ці старі файли містять старі підписи, що призводять до NoSuchMethodError.


2

Просто додавання до існуючих відповідей. Я зіткнувся з цим питанням із Tomcat у затемненні. Я змінив один клас і зробив наступні кроки,

  1. Очистив і побудував проект у екліпсісі

  2. mvn чистий встановити

  3. Пережитий томат

І все-таки я зіткнувся з такою ж помилкою. Потім я очистив tomcat, очистив робочий каталог tomcat і перезапустив сервер, і моєї проблеми немає. Сподіваюся, що це комусь допоможе


1

Щоб відповісти на оригінальне запитання. Згідно з документами Java, тут :

"NoSuchMethodError" кидається, якщо програма намагається викликати визначений метод класу (статичний або екземпляр), і цей клас більше не має визначення цього методу.

Зазвичай ця помилка виявляється компілятором; ця помилка може виникнути лише під час виконання, якщо визначення класу несумісно змінено.

  1. Якщо це трапляється під час виконання, перевірте клас, що містить метод, у класі.
  2. Перевірте, чи ви додали нову версію JAR і метод сумісний.

1

Я вирішив цю проблему в Eclipse, перейменувавши тестовий файл Junit.
У своєму робочому просторі Eclipse у мене є проект програми та тестовий проект.
Тестовий проект має проект 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>

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


1

У моєму випадку у мене був мультимодульний проект, і сценарій був як com.xyz.TestClassу модулі, Aтак і в модулі, Bі модуль Aзалежав від модуля B. Тож під час створення збірної банки я думаю, що збереглася лише одна версія класу, якщо у неї немає методу, що викликається, тоді я отримувавNoSuchMethodError виключення під час виконання, але компіляція була чудовою.

Пов’язано: https://reflectoring.io/nosuchmethod/


0

Я зіткнувся з подібною проблемою, коли міняв підписи методів у своїй програмі. Очищення та відновлення мого проекту вирішило "NoSuchMethodError".


0

Вище відповідь пояснює дуже добре .. просто додати одне, якщо ви використовуєте eclipse, використовуйте ctrl + shift + T і введіть структуру пакету класу (наприклад: gateway.smpp.PDUEventListener), ви знайдете всі банки / проекти, де він присутній . Видаліть непотрібні баночки з classpath або додайте вище в шлях класу. Тепер він підбере правильний.


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файл в банку, щоб вирішити проблему.


0

У мене була така ж проблема. Це також викликано, коли в класах є неоднозначність. Моя програма намагалася викликати метод, який був присутній у двох файлах JAR, присутніх у тому самому шляху розташування / класу. Видаліть один файл JAR або виконайте свій код таким чином, що використовується лише один файл JAR. Переконайтеся, що ви не використовуєте один і той же JAR або різні версії того ж JAR, які містять один і той же клас.

DISP_E_EXCEPTION [крок] [] [Z-JAVA-105 Виняток Java java.lang.NoSuchMethodError (com.example.yourmethod)]


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, але не клас, з якого викликається метод, який містить основний () метод.

Ця проблема - це не те, що ви можете стикатися занадто часто, оскільки найчастіше проект переробляється щорічно або дія Build збирається автоматично, замість того, щоб просто складати один модифікований клас.

Моя справа полягає в тому, що я створив файл .jar, який повинен був використовуватись як виправлення, який не містив App.class, оскільки це не було змінено. Мені було доцільно не включати його, оскільки я зберігав початковий аргумент базового класу через успадкування.

Вся справа в тому, що коли ви складаєте клас, отриманий байт-код є своєрідним статичним , інакше кажучи, це жорсткий посилання .

Оригінальний розібраний байт-код (згенерований інструментом javap) виглядає так:

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

Після того, як ClassLoader завантажить новий скомпільований Bank.class, він не знайде такого методу, він здається, що він був видалений і не змінений, таким чином, названа помилка.

Сподіваюся, це допомагає.


0

Проблема в моєму випадку полягала у наявності двох версій однієї бібліотеки на шляху збирання. Старіша версія бібліотеки не мала функції, а новіша -.


0

У мене була подібна проблема з моїм проектом Gradle за допомогою Intelij. Я вирішив це, видаливши пакунок .gradle (див. Скріншот нижче) та відновивши проект. .gradle пакет


0

NoSuchMethodError: Я витратив пару годин на виправлення цієї проблеми, нарешті виправивши її, просто перейменувавши ім'я пакета, очистіть та складіть ... Спробуйте спочатку очистити збірку, якщо це не працює, спробуйте перейменувати ім’я класу чи ім'я пакета та очистити збірку. . це слід виправити. Удачі.


-2

Якщо назва вашого файлу відрізняється від імені класу, який містить основний метод, можливо, ця помилка може спричинити.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.