1. 概要

このチュートリアルでは、 java.lang.NoSuchMethodErrorとそれを処理するいくつかの方法を見ていきます。

2. NoSuchMethodError

名前が示すように、特定のメソッドが見つからない場合にNoSuchMethodErrorが発生します。 このメソッドは、インスタンスメソッドまたは静的メソッドのいずれかになります。

ほとんどの場合、 コンパイル時にこのエラーをキャッチできます。 したがって、 、それは大きな問題ではありません。 ただし、は実行時にスローされることがあり、それを見つけるのは少し難しくなります。 Oracleのドキュメントによると、クラスが互換性なく変更された場合、このエラーは実行時に発生する可能性があります。

したがって、次の場合にこのエラーが発生する可能性があります。 まず、コードの部分的な再コンパイルを実行する場合。 次に、外部jarなど、アプリケーションの依存関係バージョンの非互換性がある場合。

NoSuchMethodError 継承ツリーには、IncompatibleClassChangeErrorとLinkageErrorが含まれていることに注意してください。これらのエラーは、コンパイル後の互換性のないクラス変更に関連しています。

3. NoSuchMethodErrorの例

例を使用して、このエラーの動作を見てみましょう。 このために、2つのクラスを作成します。 1つ目はSpecialTodayで、レストランでのその日のスペシャルを一覧表示します:

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

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

2番目のクラス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

次に、 SpecialToday のメソッドgetDesert()を削除し、この更新されたクラスのみを再コンパイルします。 今回、 MainMenu、を実行すると、次のランタイムエラーが発生します。

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

4. NoSuchMethodErrorの処理方法

それでは、これをどのように処理できるかを見てみましょう。 上記のコードでは、で完全なクリーンコンパイルを実行し、両方のクラスを含めます。 コンパイル中にエラーがキャッチされることに気付くでしょう。 Eclipse のようなIDEを使用すると、 SpecialsToday を更新するとすぐに、それはさらに早く検出されます

したがって、アプリケーションでこのエラーが発生した場合は、最初のステップとして、完全にクリーンなコンパイルを実行します。 Mavenを使用して、 mvn cleaninstallコマンドを実行します。

問題は、アプリケーションの外部依存関係にある場合があります。 この場合、最初にクラスパスローダーによってプルされたビルドパス内のjarsの順序を確認します。 そして、一貫性のないjarをトレースして更新します。

ただし、実行時にこのエラーが発生する場合は、さらに深く掘り下げる必要があります。 コンパイル時とランタイムのクラスとjarが同じバージョンであることを確認する必要があります。 このために、-verbose:クラスオプションを使用してアプリケーションを実行し、ロードされたクラスをチェックできます。 次のようにコマンドを実行できます。

$ 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

実行時に、個々のjarにロードされているすべてのクラスに関するこの情報を使用して、互換性のない依存関係を追跡できます。

また、2つ以上のjarファイルに重複するクラスがないことを確認する必要があります。 ほとんどの場合、Mavenは競合する依存関係を直接制御するのに役立ちます。 さらに、 mvn依存関係: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タグを使用して依存関係を管理することもできます。 使用する the 鬼ごっこ 、問題のある依存関係を除外できます。 使用する the 鬼ごっこ 、不要な依存関係がjarまたはwarにバンドルされるのを防ぐことができます。

5. 結論

この記事では、NoSuchMethodErrorについて説明しました。 このエラーの原因とその処理方法についても説明しました。 エラーを適切に処理する方法の詳細については、Javaエラーのキャッチに関する記事を参照してください。

いつものように、この記事で紹介するコードはGitHubで入手できます。