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.