Я отримую NoSuchMethodError
помилку під час запуску програми Java. Що не так і як це виправити?
Я отримую NoSuchMethodError
помилку під час запуску програми Java. Що не так і як це виправити?
Відповіді:
Без додаткової інформації важко визначити проблему, але першопричиною є те, що ви, швидше за все, склали клас проти іншої версії класу, у якій відсутній метод, ніж тієї, яку ви використовуєте під час її запуску.
Подивіться на стек стека ... Якщо виняток з’являється при виклику методу на об’єкт у бібліотеці, ви, швидше за все, використовуєте окремі версії бібліотеки при компілюванні та запуску. Переконайтеся, що у вас є правильна версія обох місць.
Якщо виняток з’являється під час виклику методу на об'єктах, створених за допомогою створених вами класів , то ваш процес збирання здається помилковим. Переконайтесь, що файли класу, які ви фактично запущені, оновлюються при компіляції.
Caused by
розділ у сліді стека, щоб знайти клас винуватця / банку
У мене виникли ваші проблеми, і це я вирішив. Наступні кроки - це робочий спосіб додати бібліотеку. Перші два кроки я зробив правильно, але останнього не зробив, перетягнувши файл ".jar" безпосередньо з файлової системи в папку "lib" мого проекту затемнення. Крім того, мені довелося видалити попередню версію бібліотеки як із шляху збірки, так і з папки "lib".
Зауважте, що у випадку рефлексії ви отримуєте NoSuchMethodException
, тоді як при невідбиваючому коді ви отримуєте NoSuchMethodError
. Я схильний шукати в дуже різних місцях, коли стикаюся з одним проти іншого.
Якщо у вас є доступ до зміни параметрів JVM, додавання багатослівного виводу повинно дозволяти вам бачити, які класи завантажуються, з яких файлів JAR.
java -verbose:class <other args>
Коли ваша програма запускається, JVM повинен скинутись на стандартну інформацію, таку як:
...
[Завантажений junit.framework.Введіть файл: / C: /Program%20Files/junit3.8.2/junit.jar]
...
Зазвичай це виникає при використанні системи збирання типу Apache Ant, яка компілює файли java лише тоді, коли файл java новіший, ніж файл класу. Якщо зміни підпису методу та класи використовували стару версію, речі можуть бути складені неправильно. Звичайний виправлення - зробити повну перебудову (як правило, "мураха чистий", а потім "мураха").
Іноді це також може бути викликано при компіляції проти однієї версії бібліотеки, але працює проти іншої версії.
Якщо ви використовуєте Maven або інший фреймворк, і ви отримуєте цю помилку майже випадковим чином, спробуйте чисту установку, як ...
clean install
Особливо ймовірно, що це спрацює, якщо ви написали об'єкт і знаєте, що він має метод. Працювали для мене.
Це також може бути результатом використання рефлексії. Якщо у вас є код, який відображає клас і витягує метод за назвою (наприклад: з Class.getDeclaredMethod("someMethodName", .....)
), то кожного разу, коли ім'я цього методу змінюється, наприклад, під час рефактора, вам потрібно буде пам’ятати, щоб оновити параметри до методу відображення, щоб відповідати відповідності новий метод підпису, або getDeclaredMethod
виклик буде кидати a NoSuchMethodException
.
Якщо це причина, то слід стека повинен показувати точку, що викликається метод відображення, і вам просто потрібно буде оновити параметри, щоб відповідати фактичному підпису методу.
На мій досвід, це трапляється періодично, коли тестування одиничних методів / полів використовується і TestUtilities
для вилучення полів для перевірки тесту. (Як правило, із застарілим кодом, який не розроблявся з урахуванням тестування одиниць.)
Якщо ви пишете веб-сторінку, переконайтеся, що у вас немає суперечливих версій банку в глобальній каталозі бібліотеки вашого контейнера, а також у вашому додатку. Можливо, ви не обов'язково знаєте, яку банку використовує завантажувач.
напр
Ці проблеми викликані використанням одного і того ж об'єкта на тих самих двох класах. Використовувані об'єкти не містять нового методу. Додано новий клас об'єктів.
колишній:
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)
Я щойно вирішив цю помилку, перезапустивши Eclipse і запустивши додаток. Причина моєї справи може полягати в тому, що я замінюю свої вихідні файли, не закриваючи проект або Eclipse. Що спричинило різну версію класів, якими я користувався.
Спробуйте таким чином: видаліть усі файли .class у своїх каталогах проектів (і, звичайно, усі підкаталоги). Перебудувати.
Іноді mvn clean
(якщо ви використовуєте maven) не очищає файли .class, створені вручну javac
. І ці старі файли містять старі підписи, що призводять до NoSuchMethodError
.
Просто додавання до існуючих відповідей. Я зіткнувся з цим питанням із Tomcat у затемненні. Я змінив один клас і зробив наступні кроки,
Очистив і побудував проект у екліпсісі
mvn чистий встановити
І все-таки я зіткнувся з такою ж помилкою. Потім я очистив tomcat, очистив робочий каталог tomcat і перезапустив сервер, і моєї проблеми немає. Сподіваюся, що це комусь допоможе
Щоб відповісти на оригінальне запитання. Згідно з документами Java, тут :
"NoSuchMethodError" кидається, якщо програма намагається викликати визначений метод класу (статичний або екземпляр), і цей клас більше не має визначення цього методу.
Зазвичай ця помилка виявляється компілятором; ця помилка може виникнути лише під час виконання, якщо визначення класу несумісно змінено.
Я вирішив цю проблему в Eclipse, перейменувавши тестовий файл Junit.
У своєму робочому просторі Eclipse у мене є проект програми та тестовий проект.
Тестовий проект має проект App як необхідний проект на шляху збирання.
Почав отримувати NoSuchMethodError.
Тоді я зрозумів, що клас у проекті Test має те саме ім'я, що і клас у проекті App.
App/
src/
com.example/
Projection.java
Test/
src/
com.example/
Projection.java
Після перейменування тесту на правильну назву "ProjectionTest.java" виняток пішов.
У мене була така ж помилка:
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>
Залежність від небажаної версії буде виключена з вашого проекту.
У моєму випадку у мене був мультимодульний проект, і сценарій був як com.xyz.TestClass
у модулі, A
так і в модулі, B
і модуль A
залежав від модуля B
. Тож під час створення збірної банки я думаю, що збереглася лише одна версія класу, якщо у неї немає методу, що викликається, тоді я отримувавNoSuchMethodError
виключення під час виконання, але компіляція була чудовою.
Пов’язано: https://reflectoring.io/nosuchmethod/
Вище відповідь пояснює дуже добре .. просто додати одне, якщо ви використовуєте eclipse, використовуйте ctrl + shift + T і введіть структуру пакету класу (наприклад: gateway.smpp.PDUEventListener), ви знайдете всі банки / проекти, де він присутній . Видаліть непотрібні баночки з classpath або додайте вище в шлях класу. Тепер він підбере правильний.
Я зіткнувся з подібним випуском.
Caused by: java.lang.NoSuchMethodError: com.abc.Employee.getEmpId()I
Нарешті я виявив, що першопричиною є зміна типу даних змінної.
Employee.java
-> Містить змінну ( EmpId
), тип даних якої змінено з int
на String
.ReportGeneration.java
-> Отримує значення , використовуючи геттер, getEmpId()
.Ми повинні відновити банку, включивши лише модифіковані класи. Оскільки в ньому не було змін, ReportGeneration.java
я включав лише Employee.class
файл Jar. Мені довелося включити ReportGeneration.class
файл в банку, щоб вирішити проблему.
У мене була така ж проблема. Це також викликано, коли в класах є неоднозначність. Моя програма намагалася викликати метод, який був присутній у двох файлах 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
Я також зіткнувся з цією помилкою.
Моя проблема полягала в тому, що я змінив підпис методу, щось подібне
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, він не знайде такого методу, він здається, що він був видалений і не змінений, таким чином, названа помилка.
Сподіваюся, це допомагає.
У мене була подібна проблема з моїм проектом Gradle за допомогою Intelij. Я вирішив це, видаливши пакунок .gradle (див. Скріншот нижче) та відновивши проект. .gradle пакет
NoSuchMethodError: Я витратив пару годин на виправлення цієї проблеми, нарешті виправивши її, просто перейменувавши ім'я пакета, очистіть та складіть ... Спробуйте спочатку очистити збірку, якщо це не працює, спробуйте перейменувати ім’я класу чи ім'я пакета та очистити збірку. . це слід виправити. Удачі.