引用第三方jar中class,不可不知的java.lang.NoSuchMethodError

最近做项目遇到了NoSuchMethodError,定位了很久,最终才解决。

看似诡异的问题,一方面是我们疏忽,导致错误出在了我们最意想不到的地方;还有就是自身知识的匮乏,我们写的代码明明有问题,自己却不知道。

事情是这样的:

1、我在eclipse中编写自己的类DottingCfgQueryer.java,并引用了1个jar中的类aty.utils.SecurityStrUtil.escapeHtmlParam(String prams)

2、我将编译后得到的DottingCfgQueryer.class文件替换到了服务器上,但是服务器上我们用的方法,参数类型被另一个团队更改了

aty.utils.SecurityStrUtil.escapeHtmlParam(Object prams)

结果就报了java.lang.NoSuchMethodError: com.huawei.nsm.framework.utils.SecurityStrUtil.escapeHtmlParam(Ljava/lang/String;)Ljava/lang/String;

定位过程:我们将服务器上对应的jar反编译,发现参数是Object类型,本地的eclipse中对应jar参数是String类型。咋一看,Object是兼容String的,没有什么问题。最后是将本地jar换成了最新的jar,然后替换到服务器上,发现正常了。于是得出 一个推论:如果A调用了B的方法,那么在A编译后得到的class中会记录B的方法签名。执行的时候,会校验A中方法签名,是否与B中真正的签名是否一致。如果在B中没有完全一致的方法签名,就会报NoSuchMethodError.

最后我使用了jclasslib字节码查看工具,分析DottingCfgQueryer.class的字节码,发现在类的常量池中果然有1个字段CONSTANT_Methodref_info,记录了函数签名信息。

在JVM规范中,该字段占用5个字节。第一个字节是标志位,第二和第三字节记录定义该方法的类在常量池中的索引,第四和第五字节定义方法签名在常量池中的索引。

走自己的路,让别人说去吧

引用第三方jar中class,不可不知的java.lang.NoSuchMethodError

相关文章:

你感兴趣的文章:

标签云: