当应用程序试图调用类(静态或实例)的指定方法,而该类已不再具有该方法的定义时,就会抛出 java.lang.NoSuchMethodError 错误。简单地说,就是同一个 Class 有多个版本的实现,并且在运行时调用了缺少方法的那个版本。本文总结了 NoSuchMethodError 常见原因及其解决方法,如有遗漏或错误,欢迎补充指正。
运行时抛出 NoSuchMethodError 的根本原因是什么?
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/9dec852745234cc8d6474ead55ec6f10.jpeg)
为什么同一个 Class 会出现多个版本?
-
JDK 版本不一致。常见于编译打包环境使用高版本 JDK 开发与打包,而实际运行环境的 JDK 版本较低。例如,本地项目环境 JDK 版本为 1.7,调用 Character.isAlphabetic() 方法判断当前字符是否为字母;而线上环境 JDK 版本为 1.6,在运行期间就会抛出 NoSuchMethodError 错误。
-
SNAPSHOT 版本不一致。常见于本地更新 SNAPSHOT 版本后,没有执行 mvn clean deploy 部署,导致线上环境运行时仍然引用了旧版本的 SNAPSHOT 包。
-
Maven 依赖生命周期为 provided。常见于本地依赖的某组件生命周期为 provided,所声明版本仅用于本地编译打包,而线上运行时会通过其他依赖关系加载 Jar 包。
-
同一个 Jar 包出现了多个版本。常见于 Maven 依赖未显式指定版本号,导致间接依赖版本冲突,很容易引入低版本的 Jar 包。
-
同一个 Class 出现在不同的 Jar 包中。该问题常见于代码拷贝场景,比如基于开源版本定制了一些功能,使用了新的 Maven 坐标打包发布,此时 Maven 仲裁机制失效(非常隐蔽,难以排查)。由于 JVM 类加载器对于同一个类只会加载一次,最终加载的类实现受到 Jar 包依赖的路径、类声明的先后顺序或文件加载顺序等因素的影响,很可能出现不同机器加载的类实现不一致。
哪个版本的 Class 最终会被执行?
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/e6a0c3dbde15eab06d5e49aebd9f8049.jpeg)
优先按照依赖管理 [dependencyManagement] 元素中指定的版本进行仲裁;
若无版本声明,则按照 “短路径优先” 原则(Maven2.0)进行仲裁,即选择依赖树中路径最短的版本;
若路径长度一致,则按照 “第一声明优先” 原则进行仲裁,即选择 POM 中最先声明的版本。
启动类加载器(Bootstrap ClassLoader)优先级最高,主要加载 JVM 运行时核心类,如 java.util、java.io等,这些类主要位于 $JAVA_HOME/lib/rt.jar 文件中。
扩展类加载器(Extention ClassLoader)优先级次之,主要加载 JVM 扩展类,如 swing 组件、xml 解析器等,这些类主要位于 $JAVA_HOME/lib/ext/ 目录下的 Jar 包中。
应用类加载器(Application ClassLoader),又称系统类加载器,优先级再次之,它会加载 Classpath 环境变量里定义的路径中的 Jar 包和目录,通常我们自己编写的代码或依赖的第三方 Jar 包都是由它来加载。
如何解决 NoSuchMethodError 错误?
Exception in thread "main" java.lang.NoSuchMethodError: com.xxx.AsyncAppender.append(Ljava/lang/String;)Ljava/lang/String;
at com.xxx.ProvokeNoSuchMethodError.main(ProvokeNoSuchMethodError:7)
at ……
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/7d80758c8c90e9d771d35307f9ebd38a.jpeg)
其他 Jar 包冲突问题
本文介绍的 Jar 包冲突解决方法,除了解决 java.lang.NoSuchMethodError 以外,对其他相似问题也具备一定的参考价值。
参考文章
重新看待 Jar 包冲突问题及解决方案
http://www.yangbing.club/2017/07/15/solution-for-jar-conflicts/
3 Steps to Fix NoSuchMethodErrors and NoSuchMethodExceptionshttps://reflectoring.io/nosuchmethod/
作者信息:
夏明,GitHub ID @StabilityMan,花名涯海,阿里云 ARMS & EagleEye 技术专家,2016 年加入阿里巴巴,一直从事链路追踪和 APM 监控诊断领域的相关工作。
本文缩略图:icon by 轩坊
新福利:
从11月01日开始至12月06日截止,一共五周时间,每周五我会从公众号底部留言+转发+在看综合最多的读者中抽取一名读者,免费包邮送实体新书《Flink入门与实战》,留言互动起来吧~