jar包冲突总结

目录

    • 1. jar包冲突体现
    • 2. jar包冲突分类
    • 3. 解决
    • 4. 线上jar冲突记录

1. jar包冲突体现

构建时没问题, 但运行时会报错. jar冲突一般会报如下异常:

  1. java.lang.NoClassDefFoundError
  2. java.lang.NoSuchMethodException
  3. java.lang.NoSuchFieldException

总结就是找不到预期的Class/Method/Field
但如果构建后是包含该jar包的, 那基本可以确定就是jar冲突了

2. jar包冲突分类

jar包冲突按是否是jar版本的原因, 分为版本问题和包命名问题

  • 版本问题
    同一个jar引入了两个版本A和B, 构建时取了其中一个版本A, 这时候可能会冲突:
  1. 如果A是低版本, 代码里用了高版本B的代码, 调用时就会报上述的错
  2. 如果A是高版本, 但没有兼容B版本, 代码里调用了B版本独有的代码, 也会报错
  • 包命名问题
    两个不同的jar, 因为命名不规范定义了相同的全路径Class, 构建时没问题两个jar都被构建, 但调用时有可能会报错, 之所以说有可能还与具体的机器相关
  1. 如果机器先加载A包, 调用A包同路径Class的代码就不会报错
  2. 如果机器先加载A包, 调用B包同路径Class的代码就会报错
  3. 如果机器先加载A包, 调用B包同路径Class的代码, 但A包也有相同方法签名的方法, 此时不会报错, 但是调用逻辑可能是非预期但很难发现

3. 解决

只要找到原因, 根据上述两种分类对症下药即可

  • 版本问题
    必须要求新版本兼容老版本, 强行排去老版本

  • 包命名问题

方案1: 要求jar提供方重新打包, 按规范定义Class路径
方案2: 如果对其中一个jar只依赖该Class, 可以自己反编译自己重新定义
方案3: 如果深度依赖, 想办法让双方的该Class互相兼容
方案4: 如果双方包不方便重新打包(如第三方的包), 自己反编译后兼容改造后重新打成新的jar包, 引用新的jar包

方案1最优

4. 线上jar冲突记录

  • case1
    jar包冲突总结_第1张图片
  1. a1和c1虽然不是同一个包,但是都包含一个包路径相同的工具类。
  2. 工具包包含相同的方法但是参数签名不一样,导致冲突。
  3. 最终方案是排掉其中1个

相同路径是因为: 同一个大部门不同组自己封装的工具类,所以导致包路径相同。

  • case2

jar包冲突总结_第2张图片

  1. a1引用了b1(版本v1), a3也引用了b1(版本v2),且依赖的b1版本不同
  2. 一期的时候为了解决冲突,将b1的版本显示固定为高版本v2
  3. 二期的时候a3升级了,a3的依赖包b1也升级为v3(大于v2),但由于原来b1固定版本且忘记更新,所以导致a3依赖的还是v2版本的b1,编译的时候也检查不出来,线上调用a3对应方法报错(a3调用v3版本b1的api)
  4. 最终解决方案:去掉b1固定版本,将a1对b1的依赖异常;如果后面a3升级导致b1升级就可以自动升级,如果后面a1升级导致b1升级为v4(这时候需要反过来把a3的依赖排除,a1的依赖排除放开)

你可能感兴趣的:(Java,jar,java)