如何修复NoSuchMethodError?


Answers:


225

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

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

如果在调用由类实例化对象的方法,当出现异常做,那么你的构建过程似乎是错误的。确保在编译时实际运行的类文件已更新。


3
我们最近发现了其中一种原因,结果发现构建过程是在关闭Java服务器之前将类文件放置在适当的位置,我们之所以这么做是因为Java服务器未加载某些类,然后它确实加载了一些,但是它得到了这些新代码,并且由于新代码引用了旧类没有的方法...宾果游戏,NoSuchMethodError
vazor 2015年

108

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

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

在此处输入图片说明

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

在此处输入图片说明

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

在此处输入图片说明


75
+1表示“每个人都希望您知道如何使用它,如果您不这样做,他们会否决您的问题。”
维克拉姆2012年

73

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


换句话说,如果您使用反射在类上获取方法,但未找到该方法,则会收到NoSuchMethodException。但是,如果您遇到针对某些库编译代码并且在服务器上拥有其他库(可能是新库,可能是旧库)的情况,则会收到NoSuchMethodError。如我错了请纠正我。
维克多

50

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

java -verbose:class <other args>

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

...

[从文件:/ C:/Program%20Files/junit3.8.2/junit.jar加载junit.framework.Assert]

...


3
+1辉煌!通过使用此方法,我解决了一个讨厌的小问题,谢谢。这是发现类何时以某种方式潜入类路径的绝佳方法。
邓肯·琼斯

1
+1您保存了我的一天!它只是一个库,在源中包含了具有相同名称的旧类。
安德里·内姆琴科

12

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

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


1
实际上,对于使用任何Java开发框架(Maven,NetBeans和Apache Ant)的Java程序员来说,这似乎更像是一个问题,您可以从此处的所有答案中看到。
HoldOffHunger

8

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

clean install

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


Gradle版本也是如此。
乔纳森·兰德鲁姆

4

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

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

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


3

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

例如

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

2

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

例如:

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)。


2

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

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

2

对我而言,这是因为我将函数中的参数类型从Object a更改为String a。我可以解决它并重新构建


2

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


2

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

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


2

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

  1. 在eclpise中清理并建立了项目

  2. mvn全新安装

  3. 重新启动tomcat

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


1

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

如果应用程序尝试调用类的指定方法(静态或实例),并且该类不再具有该方法的定义,则抛出“ NoSuchMethodError”。

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

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

1

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

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

App/  
  src/
     com.example/  
       Projection.java
Test/  
  src/
     com.example/
       Projection.java

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


我有一个类似的问题。我有一个具有相同完整规范名称的依赖项类。重命名后,异常消失了。
moralejaSinCuentoNiProverbio

1

我有同样的错误:

  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依赖项。

在此处输入图片说明 在此处输入图片说明

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

在属性中:

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

并作为依赖项:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
</dependency>

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

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

  <dependency>
      <groupId>group-a</groupId>
      <artifactId>artifact-a</artifactId>
      <version>1.0</version>
          <exclusions>
             <exclusion>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
             </exclusion>
         </exclusions>
  </dependency>

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


1

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

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


0

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


0

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


0

我遇到了类似的问题。

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

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

  1. Employee.java->包含变量(EmpId),其数据类型已从更改intString
  2. ReportGeneration.java->使用getter检索值getEmpId()

我们应该通过仅包含已修改的类来重新打包jar。由于没有任何变化,因此ReportGeneration.java我仅包含Employee.classin Jar文件。我必须将ReportGeneration.class文件包含在jar中才能解决此问题。


0

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

DISP_E_EXCEPTION [步骤] [] [Z-JAVA-105 Java异常java.lang.NoSuchMethodError(com.example.yourmethod)]



0

我也遇到了这个错误。

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

void invest(Currency money){...}

进入

void invest(Euro money){...}

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

public static void main(String args[]) {
    Bank myBank = new Bank();

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

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

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

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

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

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

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

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

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

希望这可以帮助。


0

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


0

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


0

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.