`

idea分析包冲突(jar包冲突原理与解决办法)

    博客分类:
  • idea
阅读更多
IDEA为我们提供了maven视图,我的是在右侧Maven Projects,
1。点击Maven Projects
2.右击想分析的module,选择show dependency
3.查看视图,选择冲突包,可以查看到被引用情况

Maven中 jar包冲突原理与解决办法
https://blog.csdn.net/noaman_wgs/article/details/81137893
Maven中jar包冲突是开发过程中比较常见而又令人头疼的问题,我们需要知道 jar包冲突的原理,才能更好的去解决jar包冲突的问题。本文将从jar包冲突的原理和解决两个方面阐述Maven中jar包冲突的解决办法。

一、Maven中jar包冲突产生原因
MAVEN项目运行中如果报如下错误:

Caused by:java.lang.NoSuchMethodError
Caused by: java.lang.ClassNotFoundException
1
2
3
十有八九是Maven jar包冲突造成的。那么jar包冲突是如何产生的?

首先我们需要了解jar包依赖的传递性。

1、依赖传递
当我们需要A的依赖的时候,就会在pom.xml中引入A的jar包;而引入的A的jar包中可能又依赖B的jar包,这样Maven在解析pom.xml的时候,会依次将A、B 的jar包全部都引入进来。

举个例子:
在Spring Boot应用中导入Hystrix和原生Guava的jar包:
<!--原生Guava API-->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>20.0</version>
</dependency>

<!--hystrix依赖(包含对Guava的依赖)-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>1.4.4.RELEASE</version>
</dependency>
利用Maven Helper插件得到项目导入的jar包依赖树:

从图中可以看出Hystrix包含对Guava jar包依赖的引用: Hystrix -> Guava,所以在引入Hystrix的依赖的时候,会将Guava的依赖也引入进来。

2、jar包冲突原理
那么jar包是如何产生冲突的?
假设有如下依赖关系:

A->B->C->D1(log 15.0):A中包含对B的依赖,B中包含对C的依赖,C中包含对D1的依赖,假设是D1是日志jar包,version为15.0

E->F->D2(log 16.0):E中包含对F的依赖,F包含对D2的依赖,假设是D2是同一个日志jar包,version为16.0

当pom.xml文件中引入A、E两个依赖后,根据Maven传递依赖的原则,D1、D2都会被引入,而D1、D2是同一个依赖D的不同版本。
当我们在调用D2中的method1()方法,而D1中是15.0版本(method1可能是D升级后增加的方法),可能没有这个方法,这样JVM在加载A中D1依赖的时候,找不到method1方法,就会报NoSuchMethodError的错误,此时就产生了jar包冲突。

注:
如果在调用method2()方法的时候,D1、D2都含有这个方法(且升级的版本D2没有改动这个方法,这样即使D有多个版本,也不会产生版本冲突的问题。)

举个例子:

利用Maven Helper插件分析得出:Guava这个依赖包产生冲突。
我们之前导入了Guava的原生jar包,版本号是20.0;而现在提示Guava产生冲突,且冲突发生位置是Hystrix所在的jar包,所以可以猜测Hystrix中包含了对Guava不同版本的jar包的引用。

为了验证我们的猜想,使用Maven Helper插件打印出Hystrix依赖的jar tree:

可以看到:Hystrix jar中所依赖的Guava jar包是15.0版本的,而我们之前在pom.xml中引入的原生Guava jar包是20.0版本的,这样Guava就有15.0 与20.0这两个版本,因此发生了jar包冲突。

二、 Maven中jar包冲突的解决方案
Maven 解析 pom.xml 文件时,同一个 jar 包只会保留一个,那么面对多个版本的jar包,需要怎么解决呢?

1、 Maven默认处理策略
最短路径优先

Maven 面对 D1 和 D2 时,会默认选择最短路径的那个 jar 包,即 D2。E->F->D2 比 A->B->C->D1 路径短 1。

最先声明优先

如果路径一样的话,如: A->B->C1, E->F->C2 ,两个依赖路径长度都是 2,那么就选择最先声明。

2、移除依赖:用于排除某项依赖的依赖jar包
(1)我们可以借助Maven Helper插件中的Dependency Analyzer分析冲突的jar包,然后在对应标红版本的jar包上面点击execlude,就可以将该jar包排除出去。

再刷新以后冲突就会消失。

(2)手动排除
或者手动在pom.xml中使用<exclusion>标签去排除冲突的jar包(上面利用插件Maven Helper中的execlude方法其实等同于该方法):

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>1.4.4.RELEASE</version>
        <exclusions>
            <exclusion>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
            </exclusion>
    </exclusions>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
mvn分析包冲突命令:

mvn dependency:tree
1
3 版本锁定原则:一般用在继承项目的父项目中
正常项目都是多模块的项目,如moduleA和moduleB共同依赖X这个依赖的话,那么可以将X抽取出来,同时设置其版本号,这样X依赖在升级的时候,不需要分别对moduleA和moduleB模块中的依赖X进行升级,避免太多地方(moduleC、moduleD….)引用X依赖的时候忘记升级造成jar包冲突,这也是实际项目开发中比较常见的方法。

首先定义一个父pom.xml,将公共依赖放在该pom.xml中进行声明:

<properties>
    <spring.version>spring4.2.4</spring.version>
<properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.versio}</version>
        </dependency>
    </dependencies>
</dependencyManagement>
1
2
3
4
5
6
7
8
9
10
11
12
13
这样如moduleA和moduleB在引用Spring-beans jar包的时候,直接使用父pom.xml中定义的公共依赖就可以:
moduleA在其pom.xml使用spring-bean的jar包(不用再定义版本):

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
    </dependency>
</dependencies>
1
2
3
4
5
6
moduleB在其pom.xml使用spring-bean的jar包如上类似:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
    </dependency>
</dependencies>
1
2
3
4
5
6
以上就是日常开发中解决Maven冲突的几个小方案,当然实际开发中jar包冲突的问题可能远远比这个更复杂,需要具体问题具体处理。

2018/07/20 15:14:00 in SH.

参考:https://blog.csdn.net/u011955252/article/details/78927427
————————————————
版权声明:本文为CSDN博主「是Guava不是瓜娃」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/noaman_wgs/article/details/81137893
分享到:
评论

相关推荐

    检测工具 jar包冲突

    "检测工具 jar包冲突"这个主题就是针对这个问题,旨在帮助开发者识别和解决这类冲突。 首先,我们需要理解为什么会出现jar包冲突。这通常是因为项目依赖管理不善导致的。例如,项目A依赖于库X(版本1),同时库Y...

    检查jar包冲突

    以下是一些关于如何检查和解决`jar`包冲突的关键知识点: 1. **冲突检测**: - **MANIFEST.MF检查**:每个`jar`包的`META-INF/MANIFEST.MF`文件可以列出其依赖项,通过比较不同`jar`包的`MANIFEST.MF`,可以初步...

    删除无用的jar包的插件

    这种插件的主要功能是分析项目的依赖关系,找出那些未被项目代码引用的jar包,并将其剔除。这样可以显著优化项目结构,减少不必要的资源占用,提高构建速度和运行性能。下面我们将深入探讨这个话题。 首先,了解...

    maven冲突jar包清理脚本

    构建maven工程时pom.xml中引入依赖时有红色字体,setting处理了,也将jar包的版本号都试了一遍,还是没解决,后来请教大牛,原来是没连网,maven工程加载了一部分jar包,连网之后自动下载的jar包跟之前的冲突,用这...

    Jar包包名修改

    3. **避免冲突**:在多模块项目中,相同的文件名可能导致冲突,通过修改JAR名可以避免这个问题。 4. **发布需求**:在发布到应用市场或第三方库仓库时,可能需要根据平台的要求更改文件名。 "Jar包包名修改"工具的...

    jar包2jar包2jar包2jar包2jar包2

    5. **jar冲突**:当多个jar包包含相同类时,可能导致冲突。使用工具如ProGuard或Shade插件可以对jar进行混淆和重命名,避免冲突。 6. **MANIFEST.MF**:manifest文件是jar包的一部分,可以包含版本信息、版权信息,...

    Jar包Jar包Jar包Jar包

    标题提到的"Jar包Jar包Jar包Jar包"可能是强调这些文件的重要性或者重复提及,而描述中的"我下载的一些Jar包,希望有人会用到,找了很久"表明这些JAR文件可能是作者收集的,可能包含了特定的功能或库,对某些项目可能...

    定位web开发中的jar包冲突

    本篇将深入探讨这个问题,以及如何通过理解ClassLoader的工作原理和使用相关工具来有效地解决jar包冲突。 首先,我们来了解什么是ClassLoader。在Java中,ClassLoader是负责加载类到JVM中的组件。当遇到多个相同类...

    asm.jar包冲突

    标题“asm.jar包冲突”揭示了我们正在讨论的是一个与Java编程语言相关的技术问题,特别是涉及到ASM库的使用。ASM是一个流行的Java字节码操控和分析框架,它被广泛用于动态代理、字节码生成以及代码分析等场景。在...

    示例源码_SpringBoot踩坑记录:IDEA+MAVEN本地 jar 包打包及引入使用_Qc20201217.zip

    在实际操作中,可能会遇到一些坑,例如依赖冲突、jar包未正确打包导致的运行错误等。解决这些问题通常需要检查pom.xml的配置,确认所有的依赖版本协调一致,且打包过程中没有遗漏任何必要的资源文件。对于运行错误,...

    IntelliJ IDEA 批量导出Maven项目依赖的jar包.docx

    ### IntelliJ IDEA 批量导出Maven项目依赖的jar包 #### 一、背景与目的 在Java开发过程中,我们经常需要使用各种第三方库或框架,这些通常是以jar包的形式存在。为了方便项目的构建和部署,我们需要将这些依赖的jar...

    idea中解决maven包冲突的问题(maven helper)

    "idea中解决maven包冲突的问题(maven helper)" Idea 中解决 Maven 包冲突的问题是日常开发中经常会遇到的一个问题。在 Idea 中,解决 Maven 包冲突的问题可以使用 Maven Helper 插件,该插件可以帮助我们快速地...

    将多个jar包合并为一个jar包

    为了简化项目结构、减少资源占用以及方便管理,开发者有时会选择将多个JAR包合并成一个单一的JAR包。这个过程被称为JAR文件的合并。本文将详细讲解如何进行这项操作,并分享一个实用的合并工具。 首先,理解JAR文件...

    IDEA2019.2汉化包

    - 检查汉化包是否与IDEA版本匹配,不同版本的IDEA可能需要不同的汉化包。 - 在安装汉化包前,最好先备份原有的配置文件,以防意外情况发生。 - 若遇到界面显示异常或部分功能失效,可能是汉化不完全或与某些插件冲突...

    idea如何导入jar包,看看这个你就明白了

    在Java开发过程中,引入外部库或jar包是常见的操作,特别是在使用IntelliJ IDEA这样的集成开发环境(IDE)时。本文将详细介绍如何在IntelliJ IDEA中高效地导入jar包,确保它们能被项目正确识别并引用。 首先,我们...

    java通用jar包

    创建jar包通常通过`jar`命令行工具或集成开发环境(IDE)如Eclipse、IntelliJ IDEA等完成。基本的`jar`命令格式为`jar cvf jar_file_name.jar file_list`,其中`c`表示创建,`v`表示详细模式,`f`指定jar文件名,`...

    java的jar包

    可以通过IDE(如Eclipse、IntelliJ IDEA)的构建工具(如Maven、Gradle)来管理这些依赖,自动下载和引入必要的JAR包,确保项目可以顺利编译和运行。 总的来说,Java的JAR包在软件开发中扮演着关键角色,它们封装了...

    spring与hibernate的包冲突

    总的来说,处理Spring与Hibernate的包冲突需要对Java项目的构建系统有深入理解,熟悉Maven或Gradle的依赖管理,以及对Spring和Hibernate的工作原理有清晰的认识。通过合理的配置管理和版本控制,可以有效地避免和...

    springboot编译jar包后无法扫描子jar包中的注解解决方法

    ### Spring Boot 编译 JAR 包后无法扫描子 JAR 包中的注解解决方案 在使用Spring Boot进行项目开发时,我们经常会遇到模块化的需求,即一个大型项目被拆分成多个子模块来提高可维护性和灵活性。这些子模块可能通过...

Global site tag (gtag.js) - Google Analytics