JavaのNoSuchMethodError
1. 概要
このチュートリアルでは、 java.lang.NoSuchMethodErrorとそれを処理するいくつかの方法を見ていきます。
2. NoSuchMethodError
名前が示すように、特定のメソッドが見つからない場合にNoSuchMethodErrorが発生します。 このメソッドは、インスタンスメソッドまたは静的メソッドのいずれかになります。
ほとんどの場合、
したがって、次の場合にこのエラーが発生する可能性があります。 まず、コードの部分的な再コンパイルを実行する場合。 次に、外部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
5. 結論
この記事では、NoSuchMethodErrorについて説明しました。 このエラーの原因とその処理方法についても説明しました。 エラーを適切に処理する方法の詳細については、Javaエラーのキャッチに関する記事を参照してください。
いつものように、この記事で紹介するコードはGitHubで入手できます。