首先介绍本文的书写思路:
* 理解NoSuchMethodError的含义
* 复现NoSuchMethodError异常
* 举一个实际的例子
* 提出解决问题的一般思路
1、 错误内容:java.lang.NoSuchMethodError: com.Boot: method <init>()V not found
此提示内容指,com.Boot没有参数为空的构造函数。提示中指明了异常所在的类和对应的函数。
2、 java文档: 说的很清楚了,是类的变化不兼容导致的异常。通俗的说法是,调用方使用的类定义和加载的类定义不一样,加载的类实际上没有将要调用的方法。
/** * 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. * <p> * Normally, this error is caught by the compiler; this error can * only occur at run time if the definition of a class has * incompatibly changed. * * @author unascribed * @since JDK1.0 */ public class NoSuchMethodError extends IncompatibleClassChangeError {
3、 如何制造一个NoSuchMethodError:
这里提供两个java代码。放在com目录下。依次执行以下命令:
javac com/Boot.java javac com/Cloud.java vim com/Boot.java 把Boot的无参构造函数注释掉,把有参构造函数的注释打开 javac com/Boot.java 重新编译Boot的类文件,最终结果没有无参构造函数 java com/Cloud 此处会出现NoSuchMethodError异常
方法提供方 package com; public class Boot{ private String name; // public Boot (String name){ // this.name = name; // } 注意这里的两个构造函数。 public Boot (){ } public void run(){ System.out.println(name); } } ====================== 调用方 package com; import com.Boot; public class Cloud{ public Cloud (){ } public static void main(String[] args){ new Boot().run(); } }
4、原因说明
实际使用的类文件不配套导致的异常。即通常所说的jar包版本不一致导致此问题。
5、实际举例
Spring Boot 2.x 使用 feign 出现此错误。Spring Cloud 1.1调用的构造函数是 new SpringApplicationBuilder(new Object[0]) ,但Spring Boot 2.1 提供的构造函数只有一个
public SpringApplicationBuilder(Class... sources) {
this.application = this.createSpringApplication(sources);
}
java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava/lang/Object;)V at org.springframework.cloud.bootstrap.BootstrapApplicationListener.bootstrapServiceContext(BootstrapApplicationListener.java:120) at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:84) at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:62) at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127) at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:76) at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:53) at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:342) at org.springframework.boot.SpringApplication.run(SpringApplication.java:305) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1204) at com.Application.main(Application.java:22)
`
6、解决方式:换依赖jar的版本
解决此问题的思路:
A调用B,A是调用方,B是被调用方。
运行时,当A通过符号引用尝试调用B的方法时(b.methodName(args)),符号无法解析出对应的方法调用地址。出现的原因是,B的源代码修改了api并重新编译(从版本1更新到版本2且api发生了变化)。
解决方法有两个,一是修改A的调用逻辑,使之适配新的api;二是继续使用b的旧版本。