Перейти к основному содержимому

NoSuchMethodError в Java

· 4 мин. чтения

1. Обзор

В этом руководстве мы рассмотрим ошибку java.lang.NoSuchMethodError и некоторые способы ее обработки.

2. Ошибка NoSuchMethodError

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

В большинстве случаев мы можем поймать эту ошибку во время компиляции. Следовательно , это не большая проблема. Однако иногда его можно было выкинуть во время выполнения , тогда найти его становится немного сложно. Согласно документации Oracle , эта ошибка может возникнуть во время выполнения, если класс был изменен несовместимым образом.

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

Обратите внимание, что дерево наследования NoSuchMethodError включает в себя IncompiledClassChangeError и 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 .

Иногда проблема связана с внешними зависимостями нашего приложения. В этом случае мы сначала проверим порядок банок в пути сборки, извлеченном загрузчиком пути к классам. И мы отследим и обновим несовместимую банку.

Однако, если мы все еще сталкиваемся с этой ошибкой во время выполнения, нам придется копать глубже. Мы должны убедиться, что классы и jar-файлы Compile-time и Runtime имеют одинаковые версии . Для этого мы можем запустить приложение с параметром -verbose: class для проверки загруженных классов. Мы можем запустить команду следующим образом:

$ java -verbose:class com.foreach.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

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

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

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

Мы можем проверить библиотеки и их версии в списке, сгенерированном этой командой. Более того, мы также можем управлять зависимостями с помощью тегов maven. Используя тег <exclusions> , мы можем исключить проблемную зависимость. Используя тег <Optional> , мы можем предотвратить объединение нежелательных зависимостей в jar или war.

5. Вывод

В этой статье мы рассмотрели NoSuchMethodError . Мы обсудили причину этой ошибки, а также способы ее устранения. Для получения более подробной информации о том, как правильно обрабатывать ошибки, обратитесь к нашей статье об отлове ошибок Java .

Как всегда, код, представленный в этой статье, доступен на GitHub.