NoSuchMethodError 错误——包冲突解决办法
包冲突的解决办法
注意所有关于maven的pom文件的改动,最后都要reimport一下,IDE会强制根据新的pom.xml设置重新分析并加载依赖类包,以得到和pom.xml设置相同的依赖。(这一步非常重要哦,经常项目组pom.xml是相同的,但是就是有些人可以运行,有些人不能运行,俗称人品问题,其实都是IDE的缓存造成的了 )
包冲突的现象
运行时异常 NoSuchMethodError 就是典型包冲突异常,编译的时候并不会报错,
往往在运行的时候才会暴露问题,没有做充分验证会导致程序出现无法预知的返回结果。
运行时抛出 NoSuchMethodError 错误的根本原因就是: 应用程序直接或间接依赖了同一个类的多个版本,
并且在运行时执行了缺少方法的版本。 如下图所示:
为什么同一个 Class 会出现多个版本?
导致 Java 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 最终会被执行? 影响 Class 最终是否被执行的关键因素有两个:Maven 依赖仲裁机制和 JVM 类加载机制,如下图所示:
首先,Maven 依赖仲裁机制 决定了打包的优先级, 仲裁优先级"从高到低”如下所述:- 优先按照依赖管理 [dependencyManagement] 元素中指定的版本进行仲裁;- 若无版本声明,则按照 “短路径优先” 原则(Maven2.0)进行仲裁,即选择依赖树中路径最短的版本;- 若路径长度一致,则按照 “第一声明优先" 原则进行仲裁,即选择 POM 中最先声明的版本。
合理使用 Maven 依赖仲裁机制可以便捷的管理 Jar 包版本,而不合理的使用将导致多版本 Jar 冲突。
其次,JVM 类加载机制 决定了 Class 被加载到 JVM 的优先级, 如果同一个类出现在多个 Jar 包中,那么在双亲委派类加载机制下,加载该 Jar 包的类加载器层级越高,该 Jar 包越先被加载,它所包含的 Class 越先被执行,如上图所示:
启动类加载器(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 包都是由它来加载。
除了上述两种原因外,在同一个 ClassLoader 下,如果存在一个 Class 出现在不同的 Jar 包中,那么文件系统的文件加载顺序也可能会影响最终的加载结果。因此,应该尽量保证开发/测试/生产系统环境一致性。
如何解决 NoSuchMethodError 错误?
虽然抛出 NoSuchMethodError 错误的原因多种多样,但本质上是由于编译时类路径与运行时类路径不一致。因此,通用的定位思路可以归纳为以下 3 步:
1、定位异常 Class 的全限定类名与调用方,通常可以在应用日志抛出的异常堆栈中获取。
这里得到类名和方法名
2、定位异常 Class 的来源,
方法一
可以通过 Arthas 等在线诊断工具反编译,如 jad com.xxx.AsyncAppender,获取该类运行时的源码、ClassLoader、Jar 包位置等信息。
如果应用程序启动失败,或者无法进行在线诊断,可以考虑添加 JVM 启动参数 -verbose:class 或 -XX:+TraceClassLoading,在日志中将输出每个类的加载信息,比如来自哪个 Jar 包。
方法二
也可以使用idea查找class
根据第一步找到的类名全局检索class文件,找到冲突的类
根据方法确认应该排除哪一个类,属于哪一个jar包
3、根据ClassLoader和jar包全路径名称等信息,判断是类加载、maven仲裁或其他原因,并对应的加以解决
解决方法
如果是同一个 Jar 包的多版本问题,可以在 Maven 标签中指定实际需要的版本,或者移除间接依赖中的低版本(提示: 执行 mvn dependency:tree 命令,可以查看 Maven 依赖拓扑关系)。
mvn dependency:tree
# 根据类名过滤得到冲突jar包是从哪一个jar包引入的
mvn dependency:tree -Dverbose -Dincludes=asm:asm
例如asm的jar包冲突
[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ ridge-test ---
[INFO] com.ridge:ridge-test:jar:1.0.2-SNAPSHOT
[INFO] +- asm:asm:jar:3.2:compile
[INFO] \- org.unitils:unitils-dbmaintainer:jar:3.3:compile
[INFO] \- org.hibernate:hibernate:jar:3.2.5.ga:compile
[INFO] +- cglib:cglib:jar:2.1_3:compile
[INFO] | \- (asm:asm:jar:1.5.3:compile - omitted for conflict with 3.2)
[INFO] \- (asm:asm:jar:1.5.3:compile - omitted for conflict with 3.2)
[INFO] ------------------------------------------------------------------------
对asm有依赖有一个直接的依赖(asm:asm:jar:3.2)还有一个传递进入的依赖(asm:asm:jar:1.5.3)
承上,假设我们不希望asm:asm:jar:1.5.3出现,根据分析,我们知道它是经由org.unitils:unitils-dbmaintainer:jar:3.3引入的,那么在pom.xml中找到这个依赖,做其它的调整:
<dependency> <groupId>org.unitils</groupId> <artifactId>unitils-dbmaintainer</artifactId> <version>${unitils.version}</version> <exclusions> <exclusion> <artifactId>dbunit</artifactId> <groupId>org.dbunit</groupId> </exclusion> <!-- 这个就是我们要加的片断 --> <exclusion> <artifactId>asm</artifactId> <groupId>asm</groupId> </exclusion> </exclusions> </dependency>
再分析一下,你可以看到传递依赖没有了:
[INFO]
[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ ridge-test ---
[INFO] com.ridge:ridge-test:jar:1.0.2-SNAPSHOT
[INFO] \- asm:asm:jar:3.2:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
其他 Jar 包冲突问题
本文介绍的 Jar 包冲突解决方法,除了解决 java.lang.NoSuchMethodError 以外,对其他相似问题也具备一定的参考价值。
例如 java.lang.ClassNotFoundException,即加载不到指定类,通常是 Maven 仲裁选错了版本,如本地开发阶段调用了 1.2.0 版本,而打包时采用了 1.0.0 版本的 Jar 包。这种就属于同一个 Class 出现在不同的 Jar 包问题,若可以排除,就用 排除该依赖;如不能排除,则考虑升级或替换为其他 Jar 包,或者考虑使用 ClassLoader 隔离技术,可参考 《如果jar包冲突不可避免,如何实现jar包隔离?》。
同理,java.lang.NoClassDefFoundError 和 java.lang.LinkageError 也可以基于上述思路进行排查。
此外,如果类和方法名都保持不变,但是内部实现有变化,在多版本冲突场景下,不会抛出异常,但程序行为跟预期不一致, 此时,也可以基于上述思路进行排查诊断。
参考博客:
https://blog.csdn.net/u014515854/article/details/80407024
https://developer.aliyun.com/article/714570
NoSuchMethodError 错误——包冲突解决办法相关推荐
- maven引入hadoop_Maven引入hadoop依赖包出错解决办法
错误: ArtifactTransferException: Failure to transfer org.apache.hadoop:hadoop-hdfs:jar:2.6.0 from http ...
- 你真的知道 NoSuchMethodError 发生原因和解决办法吗
点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群"加入公众号专属技术群 来源:阿里巴巴中间件 当应用程序试图调用类(静态或实例)的 ...
- NoSuchMethodError 发生原因和解决办法
当应用程序试图调用类(静态或实例)的指定方法,而该类已不再具有该方法的定义时,就会抛出 java.lang.NoSuchMethodError 错误.简单地说,就是同一个 Class 有多个版本的实现 ...
- 手机程序安装时几种有错误提示的解决办法
错误提示一:证书过期 问题说明:软件证书过期. 解决办法:1:把手机时间调到证书的期限内(把手机时间往前调几个月)再安装,安装完毕后调回正确时间 ...
- 在R语言环境中无法载入rJava包的解决办法
问题描述: 安装包xlsx包后,运行library("xlsx")后弹出错误窗口: RGui (64-bit): Rgui.exe - 系统错误 无法启动此程序,因为计算机中丢失 ...
- SVN多用户开发 代码冲突解决办法
[SVN多用户开发]代码冲突&解决办法 SVN是一款集中式的代码存储工具,可以帮助多个用户协同开发同一应用程序. 但是SVN不能完全代替人工操作,有时也需要程序员自己进行沟通确认有效的代码. ...
- eclipse下编写android程序突然不会自动生成R.java文件和包的解决办法
eclipse下编写android程序突然不会自动生成R.java文件和包的解决办法 我的eclipse原来是好好的,什么问题都没有的,结果今天一打开新建一个android程序,发现工程里不会自动生成 ...
- eclipse android 不会自动生成R.java文件和包的解决办法
eclipse下编写android程序突然不会自动生成R.java文件和包的解决办法 我的eclipse原来是好好的,什么问题都没有的,结果今天一打开新建一个android程序,发现工程里不会自动生成 ...
- ubuntu 16.04, conda不能安装、更新包的解决办法
ubuntu 16.04, conda不能安装.更新包的解决办法 - truth的文章 - 知乎 https://zhuanlan.zhihu.com/p/36188524 昨天打算更新 pytorc ...
最新文章
- OVS端口镜像(十五)
- Linux 3.0发布
- DevOps笔记-04:DevOps工具和文化缺一不可
- Angular refreshView的执行原理
- sql慢查询问题排查
- 疑似OPPO Reno6系列新机通过工信部认证:配备6.43英寸屏 机身仅7.9mm
- MyBatis 源码自我解读
- [开源 .NET 跨平台 Crawler 数据采集 爬虫框架: DotnetSpider] [三] 配置式爬虫
- PHP开发网站全过程技术知识分析
- 深度残差网络(ResNet)详解与实现(tensorflow2.x)
- mysql sql语句集合
- 动态分配算法_【原创连载】算法素颜(第4篇):空间复杂度你真的懂了吗?
- USBCAN分析仪的配套CAN和CANFD综合测试软件LKMaster软件解决工程师CAN总线测试难题
- OSI 的七层模型有哪些?
- 【转】韩寒:跳出棋盘的棋子
- 电脑基础知识精选(硬件篇)
- wireshark 找不到wifi无线网卡的解决方法
- 贵州学计算机,在贵州省计算机学校学习计算机专业如何?
- 19、弱电工程综合布线报价多少钱一个点位?弱电入门学习
- JavaWeb专栏之(一):什么是JavaWeb?