当前位置 : 主页 > 编程语言 > java >

使用maven工具解决jar包冲突或重复加载的问题

来源:互联网 收集:自由互联 发布时间:2021-04-10
在使用maven开发项目的过程中,经常会遇到jar包重复加载或者jar包冲突的问题的,但是由于有些jar是由于maven的依赖加载自动加载进来的, 而不是开发者自己配置的,特别是当项目中p

在使用maven开发项目的过程中,经常会遇到jar包重复加载或者jar包冲突的问题的,但是由于有些jar是由于maven的依赖加载自动加载进来的,

而不是开发者自己配置的,特别是当项目中pom中配置的jar包依赖本身很多时,开发者靠自己的经验,有时很难找出是哪个jar的加载导致加载了

多余的依赖jar,从而产生冲突。

今天刚好遇到一个借用eclipse中的maven插件解决jar包依赖冲突的问题,分享一下。

项目中出现的问题如下:

Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.apache.log4j.Log4jLoggerFactory

后经网上搜索加边上大牛指点发现:

log4j-over-slf4j.jar 和 slf4j-log4j12.jar 在同一个classpath下就会出现这个错误。

解决方法:

将slf4j-log4j12.jar从相关的jar中排除

但是查看maven项目中的pom文件,自己并没有配置这个jar的依赖,猜测是maven加载其他jar引入的依赖包。

打开pom.xml文件,在Dependency Hierarchy(依赖列表)中查看jar包的依赖层次关系。

在过滤栏中输入log4j,右侧出现了log4j相关包的依赖结构,左侧则是pom.xml全部依赖包的列表展示。

直接在右侧选中zookeeper底下的slf4j的jar包,右键选择Exclude,然后保存pom.xml。这样在加载zookeeper的jar包时就不会再加载slf4j的jar包。

修改后对应的dependency文件如下:

<dependency>
 <groupId>org.apache.zookeeper</groupId>
 <artifactId>zookeeper</artifactId>
 <version>3.4.6</version>
 <exclusions>
 <exclusion>
  <artifactId>slf4j-log4j12</artifactId>
  <groupId>org.slf4j</groupId>
 </exclusion>
 </exclusions>
 </dependency>

这样就能通过filter过滤快速找到对应jar,并知道他的依赖关系,快速解决项目中的jar包冲突问题。

补充知识:解决Maven重复依赖问题(同一个jar,多个版本)

问题描述

现在开发项目,一般都会创建maven工程,用它来管理依赖实在是方便了,当然它还有其它用途。但是在实际的情况中往往会有重复依赖的问题,比如创建的工程A,依赖了b-1.0.jar,而b-1.0.jar又依赖了d-1.0.jar(这个我们本身是不能直接看到的),同时我们自己的工程又依赖了d-2.1.jar,或者工程A依赖了c-1.0.jar,c-1.0.jar依赖了d-2.0.jar,显然,d.jar有3个版本,3者之间是重复的,甚至是冲突的。如下图所示:

重复依赖会怎么样?

首先从工程角度来讲,引用了同一个Jar的不同版本,这肯定是依赖有问题,或者就是错误的。

其次,重复依赖,在项目启动过程当中可能会有一些警告信息。

当然,最重要的是引发代码异常,最常见的就是NoSuchMethod。

解决思路

寻找重复引用的jar。

定位这些Jar在哪里被引用了。

接下来需要分析舍与留,原则上保留高版本,大多数情况下是向下兼容的。但是不一定,有时候也得保留低版本,或者有时候两者都需要保留。

如果是一个工程,其实处理起来还比较好处理。但是如果有多个工程,最终我们可能将所有的依赖合在一块儿。处理起来可能会稍微麻烦些,比如工程1依赖了2.1版本,工程2依赖了2.2版本,你把工程1的2.1的依赖去掉,但同时还需要把2.2的加在工程1上面,否则可能编译不通过。

最重要的就是,调整之后,尽可能做全面测试。特别是一些间接依赖,如果去除的话,编译不会有问题,但运行起来会有问题。

具体解决过程

上述5个步骤,重点说一下1和2.

寻找重复引用的jar

观察法:把所有的jar依赖打包到同一个目录下,观察。

运行法:运行阶段会报错,一旦报错,基本上就定位到了。

扫描法:专业的测试人员,可以进行扫描jar包并统计。

搜索法:依靠maven进行搜索,这个方法在接下来会讲到。

定位Jar被依赖的地方

在maven工程处打开命令行,输入:

mvn dependency:tree -Dverbose > tree.txt

这个命令会把这个工程pom.xml里面所有的依赖通过树的形状展示出来,tree.txt:

树形结构其实看得比较清楚,里面有一些关键信息,比如:

omitted for duplicate

这个意思是依赖是重复的,当然这个没有关系。

当然还有一些冲突提醒,上图没有,如下:

omitted for conflict with 0.5.3

显示就是这个版本与0.5.3这个版本冲突了,这个也是我上面说到的搜索法,你可以直接搜索“conflict”这个单词,就可以了。当然这种方式仅限单个工程。

拿到这棵树以后,怎么办呢?

前提是我们已经知道了哪个jar包冲突了,那直接就在文本里面搜索,找到不同版本的引用之处,然后慎重考虑之后,通过exclusions标签进行去除,如下:

<dependency>
 <groupId>jaxen</groupId>
 <artifactId>jaxen</artifactId>
 <version>1.1.1</version>
 <exclusions>
 <exclusion>
  <groupId>xerces</groupId>
  <artifactId>xercesImpl</artifactId>
 </exclusion>
 </exclusions>
 </dependency>

到此结束。去除的同时需要考虑的一些问题,在解决思路里面提及了一些。希望能给大家一个参考,也希望大家多多支持易盾网络。

网友评论