Рубрики
Без рубрики

noSuchMethod в Java

Давайте посмотрим на java.lang.NoSuchMethodError и некоторые способы справиться с этим.

Автор оригинала: baeldung.

1. Обзор

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

2. noSuchMethod error

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

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

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

Обратите внимание, что дерево наследования noSuchMethod/| включает в себя IncompatibleClassChangeError и LinkageError . Эти ошибки связаны с несовместимым изменением класса после компиляции.

3. Пример ошибки noSuchMethod

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

public class SpecialToday {
    private static String desert = "Chocolate Cake";

    public static String getDesert() {
        return desert;
    }
}

Второй класс Главное меню методы вызовов из Специальные предложения сегодня:

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

Затем мы удалим метод get Desert() в Special Today и перекомпилируем только этот обновленный класс. На этот раз, когда мы запускаем наше Главное меню, мы замечаем следующую ошибку во время выполнения:

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

4. Как справиться с NoSuchMethodError

Теперь давайте посмотрим, как мы сможем справиться с этим. Для приведенного выше кода давайте сделаем полную чистую компиляцию, включая оба класса. Мы заметим, что ошибка будет обнаружена во время компиляции. Если мы используем IDE, такую как Eclipse , она будет обнаружена еще раньше, как только мы обновим Специальные предложения сегодня .

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

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

Однако, если мы все еще сталкиваемся с этой ошибкой во время выполнения, нам придется копать глубже. Мы должны убедиться, что во время компиляции и во время выполнения классы и банки имеют одинаковые версии . Для этого мы можем запустить приложение с параметром-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] -------------< com.baeldung.exceptions:nosuchmethoderror >--------------
[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. Используя тег <исключения>, мы можем исключить проблемную зависимость. Используя тег <необязательно>, мы можем предотвратить включение нежелательных зависимостей в jar или war.

5. Заключение

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

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