首页 / 知识

关于Java:如何修复NoSuchMethodError?

2023-04-13 16:02:00

How do I fix a NoSuchMethodError?

运行Java程序时出现NoSuchMethodError错误。 有什么问题,我该如何解决?


没有更多信息,很难找出问题所在,但根本原因是,您可能是针对缺少该方法的该类的另一版本编译了一个类,而不是运行该类时所使用的方法。

查看堆栈跟踪...如果在库中的对象上调用方法时出现异常,则很可能在编译和运行时使用库的不同版本。确保两个地方的版本都正确。

如果在对您所创建的类实例化的对象上调用方法时出现异常,则说明您的构建过程似乎有问题。确保在编译时实际运行的类文件已更新。


我遇到了您的问题,这就是我解决的方法。以下步骤是添加库的有效方法。我已经正确完成了前两个步骤,但是没有通过将" .jar"文件直接从文件系统拖到eclipse项目上的" lib"文件夹中来完成最后一个步骤。此外,我还必须从构建路径和" lib"文件夹中删除该库的先前版本。

第1步-添加.jar以构建路径

enter image description here

第2步-关联源和javadocs(可选)

enter image description here

步骤3-实际上将.jar文件拖到" lib"文件夹中(非可选)

enter image description here


请注意,在反射的情况下,您得到NoSuchMethodException,而在非反射代码中,您得到NoSuchMethodError。当我遇到一个与另一个相对时,我倾向于去寻找截然不同的地方。


如果您有权更改JVM参数,则添加详细的输出应使您能够查看从哪些JAR加载了哪些类。

1
java -verbose:class <other args>

运行程序时,JVM应该转储到标准输出信息,例如:

...

[Loaded junit.framework.Assert from file:/C:/Program%20Files/junit3.8.2/junit.jar]

...


这通常是在使用Apache Ant之类的构建系统时引起的,该构建系统仅在Java文件比类文件新时才编译Java文件。如果方法签名发生更改,并且类使用的是旧版本,则可能无法正确编译。通常的解决方法是进行完全重建(通常是" ant clean"然后是" ant")。

有时,当针对库的一个版本进行编译但针对不同版本运行时,也可能导致这种情况。


如果使用Maven或其他框架,并且几乎随机出现此错误,请尝试像...这样的全新安装。

1
clean install

如果您编写了对象并且知道它具有方法,则这特别可能起作用。为我工作。


这也可能是使用反射的结果。如果您具有在类上反映并按名称提取方法的代码(例如,使用Class.getDeclaredMethod("someMethodName", .....)),则方法名称每次更改时(例如在重构期间),您都需要记住将参数更新为反射方法以匹配新的方法签名,否则getDeclaredMethod调用将抛出NoSuchMethodException

如果是这个原因,那么堆栈跟踪应该显示反射方法被调用的点,您只需要更新参数以匹配实际的方法签名即可。

以我的经验,在对私有方法/字段进行单元测试并使用TestUtilities类提取字段以进行测试验证时,偶尔会遇到这种情况。 (通常使用的遗留代码在设计时并未考虑单元测试。)


如果要编写Web应用程序,请确保容器的全局库目录以及应用程序中的jar版本都不冲突。您可能不一定知道类加载器正在使用哪个jar。

例如

  • tomcat / common / lib
  • mywebapp / WEB-INF / lib

仅添加到现有答案中。我在Eclipse中遇到了tomcat的问题。我换了一堂课,并按照以下步骤做,

  • 在eclpise中清理并建立了项目

  • mvn全新安装

  • 重新启动tomcat
  • 我仍然面临着同样的错误。然后我清理了tomcat,清理了tomcat的工作目录并重启了服务器,我的问题消失了。希望这可以帮助某人


    这意味着相应的方法不在类中:

  • 如果您使用的是jar,则反编译并检查相应版本的jar是否具有正确的类。
  • 检查您是否从源代码编译了正确的类。

  • 我刚刚通过重新启动Eclipse并运行应用程序解决了该错误。
    造成这种情况的原因可能是因为我在不关闭项目或Eclipse的情况下替换了源文件。
    这导致了我正在使用的类的不同版本。


    对我来说,发生这种情况是因为我将函数中的参数类型从Object a更改为String a。我可以解决它并重新构建


    这些问题是由在相同的两个类上使用相同的对象引起的。
    已使用新对象类所包含的不包含新方法的对象。

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    filenotnull=/DayMoreConfig.conf
    16-07-2015 05:02:10:ussdgw-1: Open TCP/IP connection to SMSC: 10.149.96.66 at 2775
    16-07-2015 05:02:10:ussdgw-1: Bind request: (bindreq: (pdu: 0 9 0 [1]) 900 900 GEN 52 (addrrang: 0 0 2000) )
    Exception in thread"main" java.lang.NoSuchMethodError: gateway.smpp.PDUEventListener.<init>(Lgateway/smpp/USSDClient;)V
            at gateway.smpp.USSDClient.bind(USSDClient.java:139)
            at gateway.USSDGW.initSmppConnection(USSDGW.java:274)
            at gateway.USSDGW.<init>(USSDGW.java:184)
            at com.vinaphone.app.ttn.USSDDayMore.main(USSDDayMore.java:40)

    -bash-3.00$

    这些问题是由伴随的02类似类引起的(src中为1,jar文件中为1,此处是gateway.jar)。


    尝试这种方式:删除项目目录(以及所有子目录)下的所有.class文件。重建。

    有时mvn clean(如果您使用的是maven)不能清除javac手动创建的.class文件。这些旧文件包含旧签名,从而导致NoSuchMethodError


    我通过重命名Junit测试文件在Eclipse中解决了此问题。
    在Eclipse工作区中,我有一个App项目和一个Test项目。
    测试项目将App项目作为构建路径上的必需项目。

    开始获取NoSuchMethodError。
    然后,我意识到Test项目中的类与App项目中的类具有相同的名称。

    1
    2
    3
    4
    5
    6
    7
    8
    App/  
      src/
         com.example/  
           Projection.java
    Test/  
      src/
         com.example/
           Projection.java

    将测试重命名为正确的名称" ProjectionTest.java"后,异常消失了。


    回答原始问题。根据此处的Java文档:

    "NoSuchMethodError" Thrown if an application tries to call a specified method of a class (either static or instance), and that class no longer has a definition of that method.

    通常,此错误由编译器捕获;如果类的定义发生了不兼容的更改,则只有在运行时才会发生此错误。

  • 如果在运行时发生,请检查包含该方法的类在类路径中。
  • 检查是否添加了新版本的JAR,并且该方法兼容。

  • 我在应用程序中更改方法签名时遇到了类似的问题。
    清理和重建我的项目解决了" NoSuchMethodError"。


    上面的答案很好解释..只是添加一件事
    如果您使用的是eclipse,请使用ctrl + shift + T并输入类的包结构(例如:gateway.smpp.PDUEventListener),您将找到存在它的所有jar /项目。从类路径中删除不必要的jar或在类路径中添加以上内容。现在它将选择正确的一个。


    在我的情况下,我有一个多模块项目,场景就像com.xyz.TestClass在模块A中以及在模块B中一样,模块A依赖于模块B。因此,在创建程序集jar时,如果没有调用的方法,我认为只保留了一个版本的类,那么我得到了NoSuchMethodError运行时异常,但是编译很好。

    相关:https://reflectoring.io/nosuchmethod/


    我遇到了类似的问题。

    1
    Caused by: java.lang.NoSuchMethodError: com.abc.Employee.getEmpId()I

    最后,我确定了根本原因是更改了变量的数据类型。

  • Employee.java->包含变量(EmpId),其数据类型已从int更改为String
  • ReportGeneration.java->使用getter getEmpId()检索值。
  • 我们应该通过仅包含已修改的类来重新打包jar。由于ReportGeneration.java中没有任何变化,因此我只在Jar文件中包含了Employee.class。我必须在jar中包含ReportGeneration.class文件才能解决该问题。


    Most of the times java.lang.NoSuchMethodError is caught be compiler but sometimes it can occur at runtime. If this error occurs at runtime then the only reason could be the change in the class structure that made it incompatible.

    最佳解释:https://www.journaldev.com/14538/java-lang-nosuchmethoderror


    我也遇到了这个错误。

    我的问题是我更改了方法的签名,例如

    1
    void invest(Currency money){...}

    进入

    1
    void invest(Euro money){...}

    此方法是从类似于以下内容的上下文中调用的

    1
    2
    3
    4
    5
    6
    public static void main(String args[]) {
        Bank myBank = new Bank();

        Euro capital = new Euro();
        myBank.invest(capital);
    }

    编译器对警告/错误保持沉默,因为资本既是货币又是欧元。

    出现问题的原因是我只编译了定义方法的类-Bank,而不编译了从其中调用方法的类,其中包含main()方法。

    这个问题不是您经常遇到的问题,因为大多数情况下是手动重建项目或自动触发Build操作,而不仅仅是编译一个修改过的类。

    我的用例是,我生成了一个.jar文件,该文件将用作修补程序,该文件不包含App.class,因为未经修改。对我来说,不包含它是有意义的,因为我保留了初始参数的基类通过继承。

    问题是,当您编译类时,生成的字节码是静态的,换句话说,这是硬引用。

    原始的反汇编字节码(使用javap工具生成)如下所示:

    1
     #7 = Methodref          #2.#22         // Bank.invest:(LCurrency;)V

    在ClassLoader加载新的编译后的Bank.class之后,它将找不到这种方法,看起来好像它已被删除并没有更改,因此命名错误。

    希望这可以帮助。


    就我而言,问题是在构建路径中有相同库的两个版本。该库的旧版本没有该功能,而新版本则具有。


    我在使用Intelij的Gradle项目中遇到了类似的问题。
    我通过删除.gradle(请参见下面的屏幕截图)包并重建Project来解决它。
    .gradle软件包


    NoSuchMethodError:我花了几个小时解决了这个问题,最后通过重命名包名称,清理并构建来解决了它。如果不起作用,请先尝试清理构建,然后重命名类名或包名并清理构建。 。它应该是固定的。祝好运。


    我有同样的错误:

    1
    2
    3
    4
    5
      Exception in thread"main" java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonGenerator.writeStartObject(Ljava/lang/Object;)V
            at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:151)
            at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292)
            at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3681)
            at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3057)

    为了解决这个问题,我首先检查了模块依赖图(click in your POM the combination -> Ctrl+Alt+Shift+Uright click in your POM -> Maven -> Show dependencies),以了解库之间的冲突到底在哪里(Intelij IDEA)。在我的特定情况下,我有不同版本的Jackson依赖项。

    enter image description here enter image description here

    1)因此,我直接在项目的POM中明确添加了最高版本-这两个版本均为2.8.7。

    在属性中:

    1
    <jackson.version>2.8.7</jackson.version>

    并作为依赖项:

    1
    2
    3
    4
    5
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        jackson-databind</artifactId>
        <version>${jackson.version}</version>
    </dependency>

    2)但也可以使用依赖排除来解决。

    通过以下示例中的相同原理:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
      <dependency>
          <groupId>group-a</groupId>
          artifact-a</artifactId>
          <version>1.0</version>
              <exclusions>
                 <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    jackson-databind</artifactId>
                 </exclusion>
             </exclusions>
      </dependency>

    与有害版本的依赖关系将从您的项目中排除。


    我遇到了同样的问题。当班级中存在歧义时,也会造成这种情况。我的程序试图调用存在于相同位置/类路径中的两个JAR文件中的方法。删除一个JAR文件或执行您的代码,以便仅使用一个JAR文件。检查您使用的不是同一JAR或包含相同类的同一JAR的不同版本。

    DISP_E_EXCEPTION [step] [] [Z-JAVA-105 Java exception java.lang.NoSuchMethodError(com.example.yourmethod)]


    如果您的文件名与包含m??ain方法的类名不同,则可能是由该错误引起的。


    运行错误方法跟踪

    最新内容

    相关内容

    热门文章

    推荐文章

    标签云

    猜你喜欢