包冲突这个问题我们在开发程序时经常遇见,下面我们来分析下包冲突引起的原因及解决思路
控制台提示:
Caused by:java.lang.NoSuchMethodError Caused by: java.lang.ClassNotFoundException这种报错很大可能是maven 项目里面jar包冲突引起的。
在maven项目中当引入依赖时会将依赖的依赖一并引入到工程,例如当在项目中引入A的jar包时A的jar包又依赖了B的jar包,maven会将它们一并引入到工程。
<dependency> <groupId>io.netty</groupId> <artifactId>netty-buffer</artifactId> <version>4.1.9.Final</version> </dependency>用maven helper这个插件可以观察到 netty-buffer这个jar又依赖了netty-common这个jar包。netty-buffer对应上面说的A,netty-common对应上面说的B。 此时netty-buffer的版本为4.1.9.Final,如果开发者在pom文件又引入了netty-common的其它版本 如下图所示: 此时就netty-common这个jar包就冲突了。使用maven helper插件可以观察到: *假设程序使用了4.0.56Final这个版本的netty-commonjar包
如果此时4.0.56Final这个版本的包下面没有程序需要的某个类而在4.1.9Final这个版本的包下面才有这个类,程序运行时就会提示:
Caused by: java.lang.ClassNotFoundException如果程序需要的某个类的一个方法在4.0.56Final这个版本里面没有,在4.1.9Final这个版本才有,此时程序运行时就会提示:
Caused by:java.lang.NoSuchMethodError我们可以观察到在前面的4.1.9.Final这个版本居然是红色(没有被使用),难道是因为4.0.56这个jar包是在后面被引入的所以覆盖了前面的jar包吗? 我们发现虽然改变了依赖顺序但是还是4.0.56这个版本的jar包被使用,所以上面猜测是错误的。下面解释原因:
依赖A时和依赖E时都会引入依赖D,但是D的版本号不同,此时遵循maven默认使用jar包的策略程序会使用D(1.0.2)这个jar包。因为他的路径为2但是A下面Djar包的路径为3。
声明优先原则 A-->B-->C-->T(1.0.1) E-->F-->R-->T(1.0.2)当路径一样时(且路径不为0,即不是在pom文件里面直接引用相同jar包的不同版本),短路径优先原则失效,此时应该遵循声明优先原则,谁在前面被引用就使用谁。上面会使用T(1.0.1)这个版本。
直接引用覆盖原则 在pom文件直接引入两个不同版本的jar包时程序会使用在后面引入的那个版本的jar包,因为前面引入的那个jar包被覆盖了。解决方法 排除掉不需要的版本jar包,手动排除示例: 使用maven helper排除示例: 选择不需要的jar包版本右键然后选择exclude
特殊情况 开发过程中遇到过一次这样的情况: 某个jar包低版本差了一个程序需要的类程序提示:
Caused by: java.lang.ClassNotFoundException高版本有这个类但是另一个类里面的方法随着版本的迭代没有了,程序提示:
Caused by:java.lang.NoSuchMethodError上面这种情况好像去掉任意一个jar包(或者说使用任意一个jar包)程序都会报错,这个时候该怎么办呢。
解决思路 在将jar包的低版本和高版本之间的几个版本都用过之后发现没有一个版本能解决上面的问题,此时改变思路,这个jar包改变了没用那就去找找看是哪些jar包会用到这个jar包,然后将其它jar包的版本替换成高版本(低版本也行),问题得以解决。