NoSuchMethodError in Java – Java中的NoSuchMethodError

最后修改: 2020年 8月 19日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll look at the java.lang.NoSuchMethodError and some ways to handle it.

在本教程中,我们将探讨java.lang.NoSuchMethodError以及处理它的一些方法。

2. NoSuchMethodError

2.NoSuchMethodError

As the name suggests, the NoSuchMethodError occurs when a particular method is not found. This method can either be an instance method or a static method.

顾名思义,当一个特定的方法没有找到时,NoSuchMethodError就会发生。这个方法可以是一个实例方法,也可以是一个静态方法。

In most cases, we’re able to catch this error at compile-time. Hence, it’s not a big issue. However, sometimes it could be thrown at runtime, then finding it becomes a bit difficult. According to the Oracle documentation, this error may occur at runtime if a class has been incompatibly changed.

在大多数情况下,我们能够在编译时捕获这个错误。因此,这并不是一个大问题。然而,有时它可能在运行时被抛出,那么找到它就变得有点困难。根据Oracle文档,如果一个类被不兼容地改变,这个错误可能在运行时发生。

Hence, we may encounter this error in the following cases. Firstly, if we do just a partial recompilation of our code. Secondly, if there is version incompatibility with the dependencies in our application, such as the external jars.

因此,在以下情况下,我们可能会遇到这个错误。首先,如果我们只是对我们的代码进行了部分重新编译。其次,如果我们的应用程序中存在与依赖的版本不兼容,例如外部jars。

Note that the NoSuchMethodError inheritance tree includes IncompatibleClassChangeError and LinkageError. These errors are associated with an incompatible class change after compilation.

请注意,NoSuchMethodError继承树包括IncompatibleClassChangeErrorLinkageError。这些错误与编译后不兼容的类变化有关。

3. Example of NoSuchMethodError

3.NoSuchMethodError的例子

Let’s see this error in action with an example. For this, we’ll create two classes. First is SpecialToday which will list the specials for the day in a restaurant: 

让我们通过一个例子来看看这个错误的具体表现。为此,我们将创建两个类。首先是SpecialToday,它将列出一家餐馆当天的特价商品。

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

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

The second class MainMenu calls methods from SpecialsToday:

第二个类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();
    }
}

Here the output will be:

这里的输出将是。

Today's Specials: Chocolate Cake

Next, we’ll delete the method getDesert() in SpecialToday and recompile only this updated class. This time when we run our MainMenu, we notice the following runtime error:

接下来,我们将删除SpecialToday中的getDesert()方法,只重新编译这个更新的类。这次当我们运行我们的MainMenu时,我们注意到以下运行时错误。

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

4. How to Handle NoSuchMethodError

4.如何处理NoSuchMethodError

Now let’s see how we can handle this. For the above code, let’s do a full clean-compile, including both the classes. We’ll notice that the error will be caught while we’re compiling. If we use an IDE like Eclipse, it will be detected even earlier, as soon as we update SpecialsToday.

现在让我们来看看我们如何处理这个问题。对于上述代码,让我们做一个完整的清洁编译,包括两个类。我们会注意到,这个错误会在我们编译的时候被捕获。如果我们使用像Eclipse这样的IDE它将更早被发现,只要我们更新SpecialsToday

Hence if we run into this error with our applications, as a first step, we’ll do a full clean compile. With maven, we’ll run the mvn clean install command.

因此,如果我们的应用程序遇到这种错误,作为第一步,我们将进行全面的清洁编译。使用maven,我们将运行mvn clean install命令。

Sometimes the issue is with the external dependencies of our application. In this case, we’ll first check the order of the jars in the build path pulled by the classpath loader. And we’ll trace and update the inconsistent jar.

有时,问题出在我们应用程序的外部依赖性上。在这种情况下,我们首先要检查由classpath loader拉出的构建路径中的jar顺序。然后我们会追踪并更新不一致的jar。

However, if we still encounter this error at runtime, we’ll have to dig deeper. We’ll have to ensure that the Compile-time and the Runtime classes and jars have the same versions. For this, we can run the application with -verbose: class option to check the loaded classes. We can run the command as follows:

然而,如果我们在运行时仍然遇到这个错误,我们就必须深入挖掘。我们必须确保编译时和运行时的类和罐子有相同的版本。为此,我们可以用-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

Using this information about all the classes being loaded in the individual jars, during runtime, we can trace the incompatible dependency.

在运行时,利用这些关于在各个罐子中加载的所有类的信息,我们可以追踪不兼容的依赖关系。

We should also make sure that there are no duplicate classes in two or more jars. In most cases, maven will help control conflicting dependencies directly. Furthermore, we can run the mvn dependency: tree command to get the dependency tree of our project as follows:

我们还应该确保两个或多个罐子中没有重复的类在大多数情况下,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

We can check the libraries and their versions in the list generated by this command. Moreover, we can also manage dependencies using maven tags. Using the <exclusions> tag, we can exclude the problematic dependency. Using the <optional> tag, we can prevent unwanted dependencies from being bundled in the jar or war.

我们可以在该命令生成的列表中检查库和它们的版本。此外,我们还可以使用maven标签管理依赖关系。使用<exclusions>标签,我们可以排除有问题的依赖性。使用<optional>标签,我们可以防止不需要的依赖被捆绑在jar或war中。

5. Conclusion

5.总结

In this article, we addressed NoSuchMethodError. We discussed the cause of this error and also ways to handle it. For more details on how to handle errors properly, please refer to our article on catching Java errors.

在这篇文章中,我们讨论了NoSuchMethodError。我们讨论了这个错误的原因,也讨论了处理它的方法。关于如何正确处理错误的更多细节,请参考我们关于抓取Java错误的文章。

As always, the code presented in this article is available over on GitHub.

一如既往,本文介绍的代码可在GitHub上获得