【问题解决】记一个“奇怪”的java.lang.NoSuchMethodError错误

问题现象

近期本人负责的一个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错误。