相 关 阅 读
导读
『StabilityGuide』是阿里多位阿里技术工程师共同发起的稳定性领域的知识库开源项目,涵盖性能压测、故障演练、JVM、应用容器、服务框架、流量调度、监控、诊断等多个技术领域,以更结构化的方式来打造稳定性领域的知识库,欢迎您的加入。
- 正文开始 -
运行时抛出 NoSuchMethodError 的根本原因是什么?
为什么同一个 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 最终会被执行?
优先按照依赖管理 [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 ……
其他 Jar 包冲突问题
本文介绍的 Jar 包冲突解决方法,除了解决 java.lang.NoSuchMethodError 以外,对其他相似问题也具备一定的参考价值。
推荐工具&产品
ARMS —— 阿里云 APM 产品,支持 NoSuchMethodError 异常关键字告警
https://help.aliyun.com/document_detail/42966.html
Arthas —— Java 在线诊断工具
https://github.com/alibaba/arthas
参考文章
重新看待 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 轩坊
本号专注于后端技术、JVM问题排查和优化、Java面试题、个人成长和自我管理等主题,为读者提供一线开发者的工作和成长经验,期待你能在这里有所收获。