NoSuchMethodError
运行 Java 程序时出现错误。出了什么问题,我该如何解决?
32 回答
如果没有更多信息,很难查明问题,但根本原因是您很可能针对缺少方法的类的不同版本编译了一个类,而不是您在运行它时使用的版本。
查看堆栈跟踪...如果在对库中的对象调用方法时出现异常,则很可能在编译和运行时使用了不同版本的库。确保您在两个地方都有正确的版本。
如果在您创建的类实例化的对象上调用方法时出现异常,那么您的构建过程似乎有问题。确保在编译时更新了实际运行的类文件。
我遇到了你的问题,这就是我解决它的方法。以下步骤是添加库的一种工作方式。我已经正确完成了前两个步骤,但是我没有通过将“.jar”文件直接从文件系统拖到我的 Eclipse 项目的“lib”文件夹中来完成最后一个步骤。此外,我必须从构建路径和“lib”文件夹中删除以前版本的库。
第 1 步 - 添加 .jar 到构建路径
第 2 步 - 关联源代码和 javadocs(可选)
第 3 步 - 实际上将 .jar 文件拖入“lib”文件夹(非可选)
请注意,在反射的情况下,您会得到一个NoSuchMethodException
,而对于非反射代码,您会得到NoSuchMethodError
. 当面对一个与另一个时,我倾向于去寻找非常不同的地方。
如果您有权更改 JVM 参数,添加详细输出应该可以让您查看正在从哪些 JAR 文件加载哪些类。
java -verbose:class <other args>
当您的程序运行时,JVM 应该转储到标准输出信息,例如:
...
[从文件加载junit.framework.Assert:/C:/Program%20Files/junit3.8.2/junit.jar]
...
如果使用Maven或其他框架,并且您几乎随机收到此错误,请尝试全新安装,例如...
clean install
如果您编写了对象并且知道它具有方法,则这尤其可能起作用。
这通常是在使用像Apache Ant这样的构建系统时引起的,该系统仅在 java 文件比类文件更新时才编译 java 文件。如果方法签名更改并且类使用旧版本,则可能无法正确编译。通常的解决方法是进行完全重建(通常是“ant clean”然后是“ant”)。
有时,在针对库的一个版本进行编译但针对不同版本运行时也会导致这种情况。
我有同样的错误:
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+U
或right 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 Exclusions来解决。
通过与以下示例相同的原理:
<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>
不需要的版本的依赖将从您的项目中排除。
这也可能是使用反射的结果。如果您的代码反映在一个类上并按名称提取方法(例如: with Class.getDeclaredMethod("someMethodName", .....)
),那么只要该方法名称发生更改,例如在重构期间,您就需要记住更新反射方法的参数以匹配新方法签名,否则getDeclaredMethod
调用将抛出NoSuchMethodException
.
如果这是原因,那么堆栈跟踪应该显示调用反射方法的点,您只需要更新参数以匹配实际的方法签名。
根据我的经验,在对私有方法/字段进行单元测试以及使用TestUtilities
类提取字段以进行测试验证时,偶尔会出现这种情况。(通常使用在设计时未考虑单元测试的遗留代码。)
如果您正在编写一个 web 应用程序,请确保您的容器的全局库目录和您的应用程序中没有冲突的 jar 版本。您可能不一定知道类加载器正在使用哪个 jar。
例如
- tomcat/common/lib
- mywebapp/WEB-INF/lib
对我来说,这是因为我将函数中的参数类型从 Object a 更改为 String a。我可以用 clean 解决它并再次构建
在我的情况下,我有一个多模块项目,场景就像com.xyz.TestClass
是在模块A
中,以及在模块中B
,模块A
依赖于模块B
。因此,在创建程序集 jar 时,我认为如果没有调用的方法,则只保留一个版本的类,然后我得到NoSuchMethodError
运行时异常,但编译很好。
这意味着类中不存在相应的方法:
- 如果您使用的是 jar,则反编译并检查相应版本的 jar 是否具有正确的类。
- 检查您是否从源代码编译了正确的类。
我刚刚通过重新启动 Eclipse 并运行应用程序解决了这个错误。我的情况的原因可能是因为我在没有关闭我的项目或 Eclipse 的情况下替换了我的源文件。这导致了我正在使用的不同版本的类。
试试这个方法:删除项目目录下的所有 .class 文件(当然还有所有子目录)。重建。
有时mvn clean
(如果您使用的是 maven)不会清理由 .class 手动创建的文件javac
。而那些旧文件包含旧签名,导致NoSuchMethodError
.
只是添加到现有的答案。我在eclipse中遇到了tomcat的这个问题。我改变了一个班级并做了以下步骤,
在 eclpise 中清理并构建项目
mvn 干净安装
- 重启tomcat
我仍然面临同样的错误。然后我清理了tomcat,清理了tomcat工作目录并重新启动了服务器,我的问题就消失了。希望这可以帮助某人
回答原来的问题。根据这里的java文档:
“NoSuchMethodError” 如果应用程序尝试调用类的指定方法(静态或实例),并且该类不再具有该方法的定义,则抛出该错误。
通常,这个错误会被编译器捕获;如果类的定义发生了不兼容的更改,则此错误只会在运行时发生。
- 如果它发生在运行时,请检查包含该方法的类是否在类路径中。
- 检查您是否添加了新版本的 JAR 以及方法是否兼容。
这些问题是由于在相同的两个类中使用相同的对象造成的。使用的对象不包含新对象类包含的新方法。
前任:
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)
我通过重命名 Junit 测试文件在 Eclipse 中解决了这个问题。
在我的 Eclipse 工作空间中,我有一个 App 项目和一个 Test 项目。
Test 项目将 App 项目作为构建路径上的必需项目。
开始收到 NoSuchMethodError。
然后我意识到Test项目中的类与App项目中的类同名。
App/
src/
com.example/
Projection.java
Test/
src/
com.example/
Projection.java
将测试重命名为正确的名称“ProjectionTest.java”后,异常消失了。
NoSuchMethodError :我花了几个小时来解决这个问题,最后通过重命名包名、清理和构建来修复它......如果它不起作用,请先尝试清理构建尝试重命名类名或包名并清理构建.. .它应该被修复。祝你好运。
为什么没有人提到依赖冲突?这个常见问题可能与包含的具有不同版本的依赖项 jar 有关。详解及解决方法:https ://dzone.com/articles/solving-dependency-conflicts-in-maven
简短的回答;
添加这个 Maven 依赖项;
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<rules>
<dependencyConvergence />
</rules>
</configuration>
</plugin>
然后运行这个命令;
mvn enforcer:enforce
也许这就是你面临的问题的原因。
当我在我的应用程序中更改方法签名时遇到了类似的问题。清理和重建我的项目解决了“NoSuchMethodError”。
我有同样的问题。当类中存在歧义时也会引起这种情况。我的程序试图调用存在于同一位置/类路径中的两个 JAR 文件中的方法。删除一个 JAR 文件或执行您的代码以便只使用一个 JAR 文件。检查您没有使用相同的 JAR 或包含相同类的相同 JAR 的不同版本。
DISP_E_EXCEPTION [步骤] [] [Z-JAVA-105 Java 异常 java.lang.NoSuchMethodError(com.example.yourmethod)]
上面的答案很好地解释了..只是添加一件事如果您使用 eclipse 使用 ctrl+shift+T 并输入类的包结构(例如: gateway.smpp.PDUEventListener ),您将找到它所在的所有 jars/projects . 从类路径中删除不必要的 jar 或在类路径中添加以上内容。现在它会选择正确的一个。
我遇到了类似的问题。
Caused by: java.lang.NoSuchMethodError: com.abc.Employee.getEmpId()I
最后我确定了根本原因是改变了变量的数据类型。
Employee.java
--> 包含变量 (EmpId
),其数据类型已从 更改int
为String
。ReportGeneration.java
--> 使用 getter 检索值,getEmpId()
.
我们应该通过仅包含修改后的类来重新捆绑 jar。由于没有任何变化,ReportGeneration.java
我只包括了Employee.class
Jar 文件。我必须将ReportGeneration.class
文件包含在 jar 中才能解决问题。
大多数时候 java.lang.NoSuchMethodError 被编译器捕获,但有时它可能在运行时发生。如果此错误发生在运行时,那么唯一的原因可能是类结构的更改使其不兼容。
最佳解释:https ://www.journaldev.com/14538/java-lang-nosuchmethoderror
我也遇到过这个错误。
我的问题是我更改了方法的签名,例如
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() 方法。
这个问题你可能不会经常遇到,因为最常见的是手动重建项目或自动触发构建操作,而不是只编译一个修改后的类。
我的用例是我生成了一个 .jar 文件,该文件将用作修补程序,它不包含 App.class,因为它没有被修改。对我来说不包含它是有道理的,因为我通过继承保留了初始参数的基类。
问题是,当你编译一个类时,生成的字节码是一种静态的,换句话说,它是一个硬引用。
原始的反汇编字节码(使用 javap 工具生成)如下所示:
#7 = Methodref #2.#22 // Bank.invest:(LCurrency;)V
ClassLoader 加载新编译的Bank.class 后,找不到这样的方法,看起来好像被删除了,没有更改,因此命名为错误。
希望这可以帮助。
我的问题是在构建路径中有两个版本的同一个库。旧版本的库没有这个功能,而新版本的有。
我在使用 Intelij 的 Gradle 项目中遇到了类似的问题。我通过删除 .gradle(见下面的截图)包并重建项目来解决它。 .gradle 包
我也遇到过同样的问题。我更改了一种方法的返回类型并运行了该类的测试代码。那是我面对这个的时候NoSuchMethodError
。作为一种解决方案,我在整个存储库上运行了一次 maven 构建,然后再次运行测试代码。该问题在下一次单次测试运行中得到解决。
发生此错误的一个这样的例子:我碰巧犯了一个愚蠢的错误,即在非静态方法中访问私有静态成员变量。将方法更改为静态解决了该问题。
对我来说,这里提到的所有解决方法都不起作用。
mockito-core
从更新3.3.3
到3.4.3
修复问题。
我认为这是由于 Mockito JUnit 5 版本 3 中的 MockitoAnnotations.initMock() 方法已被弃用并替换为 MockitoAnnotations.openMocks() 引起的。
另一方面,检查本地 Maven 存储库并删除可能导致冲突的不必要的 jar 可能是值得的。但是在应用此步骤时,请注意不要删除手动安装的(或在操作前备份)。
如果您的文件名与包含 main 方法的类名不同,则可能会导致此错误。