问题现象
近期本人负责的一个SpringBoot模块出现了java.lang.NoSuchMethodError
报错,问题情况如下:
- A类提供了
setJumpType(String type)
,B类调用A类的setJumpType(String type)报错java.lang.NoSuchMethodError: com.xxx.A.setJumpType(Ljava/lang/String;)V
- 在之前的发版的程序中,B类无变更,出现以上问题后,重新编译B类问题解决。
常见该问题原因与解决方法
- 方法不存在:变更实现
- 方法签名变更(一般博客中只关注到方法名与参数列表):修正方法名与参数列表
问题分析
- 反编译代码和本地IDE源码调试均无该报错出现,方法是存在的
- 检查A类是否存在方法名称和参数类型、数量变更,发现也没问题
- 使用
javap -v
命令分析,经比较之前编译的与新编译的B类调用A类的方法签名中,返回值不同
处理方法
- 原因确定是方法签名的返回值发生变更
- 既然这个类是个DTO对象,就可以不直接用对方的DTO,重写一份放自己这边解决该问题,类似的情况只能靠发版前,在测试环境自测功能是否正常,有问题及时发现与解决
问题总结
java.lang.NoSuchMethodError
错误出现于方法不存在和签名变更的情况- 方法签名格式:
类路径.方法名(参数列表;)返回值类型
- 返回值类型:void->V; 引用->L类路径;
- 方法签名中除了类路径变更会导致ClassNotFound异常外,(方法名、参数列表、返回值类型)发生变化都会引起NoSuchMethodError错误,可根据错误原因进行处理
- 编译的class文件中不仅包含自身源文件的编译结果,还包含引用的类与方法的签名信息,一旦签名发生变更就会出现兼容性问题,可能造成NoSuchMethodError错误。