文章: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定位方式

  1. 出现”Could not initialize”、”Caused by: …”关键字一般是静态代码块发生异常导致类加载失败
  2. 如果不是静态代码块发生异常导致加载失败,异常message关键字中会明确显示缺失的类名称
  3. 查找异常栈中提示缺失的类在哪些版本的jar包中有
  4. 查看应用部署机器上应用lib包目录下,是否存在上一步骤中查出对应版本的jar包

    3.2 NoSuchMethodError排查到位步骤

  5. 会明确显示具体是哪个类,缺失了哪个方法。可以通过在JVM启动参数中增加” -XX:+TraceClassLoading”,然后重新启动系统,在系统工程日志中即可看到JVM加载类的信息。

  6. 在IDEA中(快捷键Ctrl+N)查找异常栈中提示缺失的类在哪些版本的jar包中有
  7. 查看应用部署机器上应用lib包目录下的jar包加载顺序

四、解决依赖冲突的办法

4.1 升/降级jar包解决依赖冲突

一般是jar包版本过低的原因导致,一般可以升级jar来解决,这种方式一定程度上需要高版本的jar向下兼容。可用工具IDEA Maven Helper。

4.2 排除jar包解决依赖冲突

容器加载的类并非预期中的类,并且这些类没有被使用或者排除后对业务无影响,可以通过exclude方式解决。