NoSuchMethodError у Java

1. Огляд

У цьому підручнику ми розглянемо java.lang.NoSuchMethodError та деякі способи його обробки.

2. NoSuchMethodError

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

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

Отже, ми можемо зіткнутися з цією помилкою у наступних випадках. По-перше, якщо ми виконуємо лише часткову перекомпіляцію нашого коду. По-друге, якщо версія несумісна із залежностями нашого додатку, такими як зовнішні банки.

Зверніть увагу, що дерево успадкування NoSuchMethodError включає IncompatibleClassChangeError та LinkageError. Ці помилки пов'язані з несумісною зміною класу після компіляції.

3. Приклад NoSuchMethodError

Давайте розберемо цю помилку в дії на прикладі. Для цього ми створимо два класи. По-перше, SpecialToday, де буде вказано спеціальні пропозиції на день у ресторані:

public class SpecialToday { private static String desert = "Chocolate Cake"; public static String getDesert() { return desert; } }

Другий клас MainMenu викликає методи SpecialsToday:

public class MainMenu { public static void main(String[] args) { System.out.println("Today's Specials: " + getSpecials()); } public static String getSpecials() { return SpecialToday.getDesert(); } }

Тут результат буде:

Today's Specials: Chocolate Cake

Далі ми видалимо метод getDesert () у SpecialToday і перекомпілюємо лише цей оновлений клас. Цього разу, коли ми запускаємо наше MainMenu, ми помічаємо таку помилку виконання:

Exception in thread "main" java.lang.NoSuchMethodError: SpecialToday.getDesert()Ljava/lang/String;

4. Як обробляти NoSuchMethodError

А тепер давайте подивимося, як ми можемо з цим впоратися. Для вищевказаного коду давайте виконаємо повну компіляцію, включаючи обидва класи. Ми помітимо, що помилка буде виявлена ​​під час компіляції. Якщо ми використовуємо IDE, як Eclipse , він буде виявлений ще раніше, як тільки ми оновимо SpecialsToday .

Отже, якщо ми натрапимо на цю помилку з нашими програмами, на першому кроці ми виконаємо повне чисте компілювання. За допомогою maven ми запустимо команду mvn clean install .

Іноді проблема полягає у зовнішніх залежностях нашої програми. У цьому випадку ми спочатку перевіримо порядок банок у шляху побудови, витягнутий навантажувачем classpath. І ми прослідкуємо та оновимо невідповідну jar.

Однак, якщо ми все ще стикаємося з цією помилкою під час виконання, нам доведеться копати глибше. Нам доведеться переконатися, що класи та банки Compile-time та Runtime мають однакові версії . Для цього ми можемо запустити додаток з опцією -verbose: class, щоб перевірити завантажені класи. Ми можемо запустити команду наступним чином:

$ java -verbose:class com.baeldung.exceptions.nosuchmethoderror.MainMenu [0.014s][info][class,load] opened: /usr/lib/jvm/java-11-openjdk-amd64/lib/modules [0.015s][info][class,load] opened: /usr/share/java/java-atk-wrapper.jar [0.028s][info][class,load] java.lang.Object source: shared objects file [0.028s][info][class,load] java.io.Serializable source: shared objects file

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

Ми також повинні переконатися, що в двох або більше баночках немає повторюваних класів . У більшості випадків maven допоможе безпосередньо контролювати конфліктні залежності . Крім того, ми можемо запустити команду mvn dependency: tree, щоб отримати дерево залежностей нашого проекту наступним чином:

$ mvn dependency:tree [INFO] Scanning for projects... [INFO] [INFO] --------------------------- [INFO] Building nosuchmethoderror 0.0.1-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ nosuchmethoderror --- [INFO] com.baeldung.exceptions:nosuchmethoderror:jar:0.0.1-SNAPSHOT [INFO] \- org.junit:junit-bom:pom:5.7.0-M1:compile

Ми можемо перевірити бібліотеки та їх версії у списку, створеному цією командою. Більше того, ми також можемо управляти залежностями за допомогою тегів maven. Використаннятег, ми можемо виключити проблемну залежність. Використання тег, ми можемо запобігти попаданню небажаних залежностей у банку або війну.

5. Висновок

У цій статті ми розглянули NoSuchMethodError . Ми обговорили причину цієї помилки, а також способи її усунення. Щоб отримати докладнішу інформацію про те, як правильно обробляти помилки, зверніться до нашої статті про виявлення помилок Java.

Як завжди, код, представлений у цій статті, доступний на GitHub.