文章:Java依赖冲突高效解决之道
文章:https://mp.weixin.qq.com/s/0G5kLzz8Mtwf2hchB8ba7A
一、背景
Jar包依赖冲突是我们在开发过程中会经常遇到的高频问题之一。部分的依赖冲突可以根据报错Error信息来解决,但是也有部分情况是,Error报错和Jar冲突没有任何的关联,导致开发人员需要花费较长时间来定位问题解决冲突。根据我个人的经验,在很多legacy的web项目中,研发人员常常会因为升级inf-bom版本而产生jar包冲突,导致项目不能启动。
二、冲突的和根本原因
2.1 JAR开发上线的过程
- 编译阶段
两个相同jar包不同version,会根据仲裁结果指定一个version并下载到指定目录下,作为最终的加载目标。
- 上线发布
一个类型实例是通过全类名和ClassLoader来决定的。容器类和应用类会通过不同的ClassLoader来加载相同的依赖来实现“类隔离”,这样就避免了容器和应用的依赖冲突。比如:该场景可解决中间件依赖类和应用依赖类发生依赖冲突问题。
发生类冲突的本质原因:要么是因为maven依赖仲裁jar包不满足运行时需要,要么是容器类加载过程中加载的类不满足运行时需要导致的。
三、依赖冲突的定位技巧
发生依赖冲突主要表现为系统启动或运行中会发生异常,99%表现为三种NoClassDefFoundError、ClassNotFoundException、NoSuchMethodError。
3.1 NoClassDefFoundError、ClassNotFoundException定位方式
- 出现”Could not initialize”、”Caused by: …”关键字一般是静态代码块发生异常导致类加载失败
- 如果不是静态代码块发生异常导致加载失败,异常message关键字中会明确显示缺失的类名称
- 查找异常栈中提示缺失的类在哪些版本的jar包中有
查看应用部署机器上应用lib包目录下,是否存在上一步骤中查出对应版本的jar包
3.2 NoSuchMethodError排查到位步骤
会明确显示具体是哪个类,缺失了哪个方法。可以通过在JVM启动参数中增加” -XX:+TraceClassLoading”,然后重新启动系统,在系统工程日志中即可看到JVM加载类的信息。
- 在IDEA中(快捷键Ctrl+N)查找异常栈中提示缺失的类在哪些版本的jar包中有
- 查看应用部署机器上应用lib包目录下的jar包加载顺序
四、解决依赖冲突的办法
4.1 升/降级jar包解决依赖冲突
一般是jar包版本过低的原因导致,一般可以升级jar来解决,这种方式一定程度上需要高版本的jar向下兼容。可用工具IDEA Maven Helper。
4.2 排除jar包解决依赖冲突
容器加载的类并非预期中的类,并且这些类没有被使用或者排除后对业务无影响,可以通过exclude方式解决。
