JAR包冲突不可避免
maven依赖管理的方式决定了jar包冲突不可避免,举个例子:在项目中引入了zookeeper jar 包依赖,但zookeeper 内部还会依赖于其他的 jar 包,从而形成一种链式的传递依赖,即A->B->C->D1。在一个项目中,这种链式的传递依赖线路是多条的,最终表现为tree,假设另一条链路为E->F->D2,这里的D1和D2分别为D的不同版本,就产生了JAR包冲突。
maven 解析 pom.xml 文件时,同一个 jar 包最终只会保留一个,这样有效的避免因引入两个 jar 包导致的工程运行不稳定性。那么在上面的描述中,maven会保留D1还是D2呢?
maven选择冲突JAR包的策略:
- 最短路径优先
Maven 面对 D1 和 D2 时,会默认选择最短路径的那个 jar 包,即 D2。E->F->D2 比 A->B->C->D1 路径短 1。 - 最先声明优先
如果路径一样的话,举个🌰: A->B->C1, E->F->C2 ,两个依赖路径长度都是 2,那么就选择最先声明。
maven选择冲突JAR的策略在编译阶段是没有问题的,但在运行阶段可能存在隐患。如在A->B->C1, E->F->C2这个例子中,A使用C1编译,E使用C2编译,但在运行时都是基于C1运行,这里假设C2版本>C1,那么在运行环境可能出现这样的问题,项目基于E调用C2的api中,可能会发现某个方法在C1这个低版本的jar包中不存在,此时会抛出NoSuchMethodException、NoSuchFieldError、NoClassDefFound等异常,也有可能方法的参数不一致,抛出AbstractMethodError等异常。在出现类似异常时,如何定位引发冲突的jar包及怎么解决冲突?
如何定位引发冲突的JAR包
操作背景:order-hall 接入 esclientrhl
<dependency>
<groupId>cn.zxporz</groupId>
<artifactId>esclientrhl</artifactId>
<vers