Java项目开发时经常会出现jar包冲突,导致项目无法启动或者运行期间报错,比如经常碰到的运行时异常ClassNotFoundException或NoSuchMethodError。本文从产生原因和解决办法两个方面去讲解。

首先了解下maven的机制。在Java项目中,我们经常用到maven来构建,应该都比较熟悉它的用法。现在简单回顾一下它的概念和作用。Maven 可以统一管理所有的依赖 jar,甚至是不同的版本。程序员也可以动态地将自己写好的模块打包成 jar 包让它管理。需要的时候,可以直接通过简单的描述文件告诉 Maven,它会自动帮助程序员找出来,集成到项目中。并且它提供了中央仓库,能帮我们自动下载构件。下面从maven角度去理解为何会出现冲突:

  • Jar包冲突的原因分析

maven存在传递依赖性的机制,举例来说,当我们需要依赖A的时候,会在pom文件里加入A.jar的依赖;如果A.jar中又依赖B.jar,那么maven解析pom时会将A和B同时引入进来:

A-->B-->C->fastjson(1.2.69)

假如项目又依赖H,而H的依赖传递关系路径为:H-->K-->fastjson(1.1.46),按照依赖传递机制和默认的依赖调解机制,优先选择1.1.46版本的fastjson,1.2.169版本的不会被引用。这里的默认依赖调解机制是指:1、路径最短原则 2、第一声明优先。因为1.1.46路径最短,所以优先引用该版本。

如果C的方法调用1.2.169版本fastjson的类或方法,而1.1.46里又没有定义该类或方法,那么JVM去加载对应类时会发现1.1.46没有该类,就会抛出ClassNotFoundException,调用对应不存在的方法时会抛出NoSuchMethodError。

  • 定位冲突思路 idea默认自带查看依赖图的插件,首先选择右侧的Maven标签

 

javacv包冲突 java包冲突怎么解决_javacv包冲突

然后选择重新加载所有依赖

 

javacv包冲突 java包冲突怎么解决_json_02

选择项目里某个module,我选择如图rocketmq-client

javacv包冲突 java包冲突怎么解决_jar_03

点击如图的按钮(show Dependencies...)或者打开pom文件,鼠标右键点击

javacv包冲突 java包冲突怎么解决_maven_04

idea计算依赖图并显示

javacv包冲突 java包冲突怎么解决_json_05

如果项目依赖关系复杂,需要等几秒,否则会很快展现依赖图:

javacv包冲突 java包冲突怎么解决_javacv包冲突_06

如果想放大查看,可以点击上面放大按钮 Zoom Out

javacv包冲突 java包冲突怎么解决_maven_07

图中出现红色虚线,表明junit包重复引用:

javacv包冲突 java包冲突怎么解决_javacv包冲突_08

点击关系图线,系统会将关系图线加粗,通过明显的方式查看jar包从哪一个位置依赖过来,从而就可以更清晰的查看jar包关系

javacv包冲突 java包冲突怎么解决_maven_09

红色虚线代表包冲突,如图所示:byte-buddy:1.9.3和bye-buddy:1.9.0不同版本,出现冲突,选择某个版本的jar包,右键选择Exclude,排除即可。

javacv包冲突 java包冲突怎么解决_json_10

当然也可以筛选只查看冲突或重复依赖的关系图:

javacv包冲突 java包冲突怎么解决_json_11

结果如图所示:

javacv包冲突 java包冲突怎么解决_javacv包冲突_12

如图案例,其中byte-buddy就是冲突依赖,出现1.9.3 和1.9.0两个版本的包依赖:

javacv包冲突 java包冲突怎么解决_maven_13