如何解决包冲突问题

下面举一个包冲突的例子:

你引用了 2 个三方包 a.jar 和 b.jar , a.jar 中又引用了一个 c.jar ,假设 c.jar 的版本号为 version-1, b.jar 中也引用了 c.jar ,假设这里的 c.jar 相对于 a.jar 中的 c.jar 为较高版本,记为 version-2 , b.jar 中某个类引用了 c.jar 的类 classA 中的方法 method A() ,并且该方法只存在于高版本的 c.jar(version-2) 的类 classA 中,而不存在c.jar(version-1) 的类 classA 中。

当系统编译加载时,系统可能编译加载 c.jar(version-1) ,也可能编译加载 c.jar(version-2) ,当编译加载c.jar(version-2) 时,由于很多 jar 包都支持向下兼容,即高版本兼容低版本,因此不论 a.jar 调用 c.jar 还是 b.jar 调用 c.jar 一般都不会出问题。但如果此时刚好应用编译加载的是 c.jar(version-1) 中的类 classA 时,那么 b.jar 调用Method A() 时便会报上述错误,因为 Method A() 函数只存在于高版本的 c.jar 中,而此时系统编译加载的却是低版本的 c.jar 。

jar包冲突常见的异常为找不到类(java.lang.ClassNotFoundException)、找不到具体方法(java.lang.NoSuchMethodError)、字段错误( java.lang.NoSuchFieldError)或者类错误(java.lang.LinkageError)

常见的解决方法如下:

1、首先做法是打出工程文件的依赖树,将根据jar包依赖情况判定是不是同一个jar包依赖了多个版本,如果确认问题所在,直接exclusion其中错误的jar包即可;

2、如果通过看依赖树不能确定具体冲突的jar包,可以使用添加jvm参数的方式启动程序,将类加载的具体jar信息打印出来;-verbose:class;

3、经过上述步骤基本就可以解决jar包冲突问题,具体的问题要具体分析,当问题不可重现时上述方法均不会奏效。

排包方法:

<dependency>
  <groupId>com.know.diamond</groupId>
  <artifactId>diamond-sdk</artifactId>
  <version>2.0.5</version>
  <exclusions>
      <exclusion>
        <groupId>com.google.collections</groupId>
         <artifactId>google-collections</artifactId>
   </exclusion>
   </exclusions>
</dependency>

当遇到jar包冲突时,我们首先确定是哪个jar包冲突了,这个很容易,看我们调用的类或方法,是属于哪个Jar包。然后就是要找出冲突了,我这里使用命令

mvn dependency:tree -Dverbose -Dincludes=<groupId>:<artifactId>

填写上Jar包的groupId和artifactId,可以只有一个,但是中间的冒号不要少,这样就会输出依赖树,而且是仅包含这个Jar包的依赖树,这样那些地方依赖了这个Jar包的那个版本就一目了然了。
例如,我的项目中notify-common包存在冲突,我们使用命令
mvn dependency:tree -Dverbose -Dincludes=:notify-common
得到依赖树输出

[INFO] com.taobao.wlb:bis-server:war:1.0-SNAPSHOT
[INFO] +- com.taobao.wlb:bis-core:jar:1.0-SNAPSHOT:compile
[INFO] |  \- com.taobao.logistics:schedule-client:jar:1.1.1:compile
[INFO] |     \- (com.taobao.notify:notify-common:jar:1.8.15:compile - omitted for conflict with 1.8.19.26)
[INFO] \- com.taobao.notify:notify-tr-client:jar:1.8.19.26:compile
[INFO]    +- com.taobao.notify:notify-common:jar:1.8.19.26:compile
[INFO]    \- com.taobao.notify:notify-remoting:jar:1.8.19.26:compile
[INFO]       \- (com.taobao.notify:notify-common:jar:1.8.19.26:compile - omitted for duplicate) 

看一下依赖树中所有的叶子节点就是所有的notify-common包,我们可以看到我们依赖的bis-core中依赖了schedule-client包,它依赖了一个notify-common包,版本是1.8.15,第四行的后面也提示了这个包同其他包有冲突
- omitted for conflict with 1.8.19.26)。而我们的系统依赖的notify-tr-client包所依赖的版本是1.8.19.26,于是我们知道是这里冲突了,在POM排除掉依赖,OK了。

说明

这里我们对我们执行的命令做一个简单的说明。
mvn dependency:tree -Dverbose -Dincludes=<groupId>:<artifactId>
第一部分mvn dependency:tree是maven依赖的分析命令,作用是对我们的项目的依赖进行分析,并输出项目依赖树。

第二部分-Dverbose的作用是添加了verbose一个环境变量,起的作用是在分析项目依赖时输出明细,这样项目中依赖的所有引用都会被输出出来,包含了所有的间接引用,会有很多很多,我们只需要我们要找的,所以就需要第三个参数了。

第三部分-Dincludes=<groupId>:<artifactId>的作用就是进行过滤,只包含我们想要的依赖的依赖时,排除掉其它不需要的,依赖树的所有叶子节点就是我们的找的依赖包。其中的groupId和artifactId可以只填写一个,为了保证准确性,一般都会填两个(填写时不包括尖括号)。

其他方法:

1、对于maven工程,我的办法是使用eclipse来解决,点开pom.xml,切换到hierarchy dependency,右上角搜索对应的包,可以清晰地看到冲突版本

2、可以使用idea,在pom.xml中右单击 选择Diagrams-》show dependencies

3、mvn dependency:tree -Dverbose > tree.log 
直接输出冲突的jar文件

时间: 2024-10-05 04:01:19

如何解决包冲突问题的相关文章

Maven类包冲突终极三大解决技巧 mvn dependency:tree

Maven对于新手来说是<步步惊心>,因为它包罗万象,博大精深,因为当你初来乍到时,你就像一个进入森林的陌生访客一样迷茫. Maven对于老手来说是<真爱配方>,因为它无所不能,利如刀锋,使用Maven做开发,如饮美酒如悦美人. Maven对于新手来说,最痛苦的一件事莫过于包之间的冲突,由于Maven的依赖传递性,当你引入一个依赖类时,其身后的依赖类也一起如过江之鲫纷至沓来了. 举例 A依赖于B及C,而B又依赖于X.Y,而C依赖于X.M,则A除引B及C的依赖包下,还会引入X,Y,M

Jar包冲突解决方法

前言 对于Jar包冲突问题,我们开发人员经常都会有碰到,当我们使用一些jar包中的类.方法等,或者有时遇到一些日志系统的问题(参考另一篇文章Jar包冲突导致的日志问题),我们会遇到ClassNotFoundException,NoSuchFieldException,NoSuchMethodException 之类的运行时异常,从经验上我们就会判断,Jar包冲突了.解决Jar包冲突问题,每个人都有每个人的方法,这里我介绍一下我的方法,供大家参考. 处理方法 当遇到jar包冲突时,我们首先确定是哪

Maven 解决JAR包冲突

在JAR 冲突的情况下, 利用Eclipse方式解决JAR包冲突时比较方便简洁的,步骤如下 1. 在Eclipse 中打开pom.xml , 选择  “Dependency  Hierarchy” 2, 在Filter 输入框中,输入冲突的jar,  比如: slf4j 3. 右边会显示所有依赖此包的JAR包 4.  如果你需要排除 冲突, 可以右键单击: 选择  exclude Maven artifact... 进行以上操作后, MAVEN 的依赖关系如下(举列如下:) 排除前: <depe

sbt发布assembly解决jar包冲突问题 deduplicate: different file contents found in the following

一.问题定义 最近在用sbt打assembly包时出现问题,在package的时候,发生jar包冲突/文件冲突问题,两个相同的class来自不同的jar包在classpath内引起冲突. 具体是:我有一个self4j的jar, 还有一个hadoop-common-hdfs的jar包,其中hadoop-common-hdfs.jar内包含了self4j这个jar包,导致冲突. 此类异常一般是由于打包不规范和打包疏忽引起的. (个人认为正确的打包策略是:只打包自己核心功能,不将依赖打包在一起,但是有

共享库方案解决WAS中JAR包冲突

(一)证书导入解决方案 1.登录管理控制台. 2. 展开"安全性"并单击"SSL 证书和密钥管理".在"配置设置"下面,单击"管理端点安全配置". 3. 为 (cell):server5Cell01 管理作用域选择适当的出站配置. 4. 在"相关项目"下面,单击"密钥库和证书",然后单击 CellDefaultTrustStore 密钥库. 5.  在"其他属性"下面

YARN环境中应用程序JAR包冲突问题的分析及解决

Hadoop框架自身集成了很多第三方的JAR包库.Hadoop框架自身启动或者在运行用户的MapReduce等应用程序时,会优先查找Hadoop预置的JAR包.这样的话,当用户的应用程序使用的第三方库已经存在于Hadoop框架的预置目录,但是两者的版本不同时,Hadoop会优先为应用程序加载Hadoop自身预置的JAR包,这种情况的结果是往往会导致应用程序无法正常运行. 下面从我们在实践中遇到的一个实际问题出发,剖析Hadoop on YARN 环境下,MapReduce程序运行时JAR包查找的

java jar包冲突解决方法

jar包冲突几乎是每个java程序员都会遇到的问题,而且特别是大工程,jar包各种依赖,经常性发生包冲突.通常会报这样几个运行时异常: java.lang.NoSuchMehodError java.lang.NoClassDefFoundError 这类问题十有八九都是jar包冲突引起,要解决jar包冲突问题,我们先了解下导致这个冲突的原因. 导致jar包冲突的原因 1.mvn的传递依赖特性:mvn编译打包除了会引入直接申明的依赖,还会引入间接申明的依赖 2.mvn的依赖仲裁规则: 1). 按

java 包冲突解决方法

1.诊断包冲突 java.lang.NoSuchMethodError: org.apache.commons.io.output.DeferredFileOutputStream.<init>(ILjava/lang/String;Ljava/lang/String;Ljava/io/File;)V 2.解决 2.1 可见的依赖冲突 在eclipse中打开工程,在pom文件的dependency hierarchy中,搜冲突的包commons-io,查看各依赖包的依赖信息.包有依赖冲突的话,

正确配置jstl的maven依赖,jar包冲突的问题终于解决啦

困扰了两天的问题,非常头疼,今天终于有了解决思路了,说到底,还是对maven不够了解吧.总是抱怨maven不好用,出现各种无厘头的问题,原来这些都是归于对它不够了解不够熟悉,它提供了很好的解决思路,只是我们通常都不知道. 问题背景: 配置jstl依赖惹的祸, <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl-api</artifactId> <ve