转载请注明出处:

1.Jar包冲突的通常表现

Jar包冲突往往是很诡异的事情,也很难排查,但也会有一些共性的表现。

  • 抛出java.lang.ClassNotFoundException:典型异常,主要是依赖中没有该类。导致原因有两方面:第一,的确没有引入该类;第二,由于Jar包冲突,Maven仲裁机制选择了错误的版本,导致加载的Jar包中没有该类。

  • 抛出java.lang.NoSuchMethodError:找不到特定的方法。Jar包冲突,导致选择了错误的依赖版本,该依赖版本中的类对不存在该方法,或该方法已经被升级。

  • 抛出java.lang.NoClassDefFoundError,java.lang.LinkageError等,原因同上。

  • 没有异常但预期结果不同:加载了错误的版本,不同的版本底层实现不同,导致预期结果不一致。

2.Jar包冲突的本质

Jar包冲突的本质:Java应用程序因某种因素,加载不到正确的类而导致其行为跟预期不一致

具体分两种情况:

  • 情况一:项目依赖了同一Jar包的多个版本,并且选错了版本;

  • 情况二:同样的类在不同的Jar包中出现,导致JVM加载了错误的类;

  情况一,同一个依赖引入了多个Jar包版本,不同的Jar包版本有不同的类和方法。由于Maven依赖树的仲裁机制导致Maven加载了错误的Jar包,从而导致Jar包冲突;

  情况二,同一类在不同的Jar包中出现。这种情况是由于JVM的同一个类加载器对于同一个类只会加载一次,现在加载一个类之后,同全限定名的类便不会进行加载,从而出现Jar包冲突的问题。

  针对第二种情况,如果不是类冲突抛出了异常,你可能根本意识不到,所以就显得更为棘手。这种情况就可以采用前文所述的通过分析不同类加载器的优先级及加载路径、文件系统的文件加载顺序等进行调整来解决。

3.解决Jar包冲突的方法

  几种场景下解决Jar冲突的方法:

    • Maven默认处理:路径最近者优先和第一声明优先;

    • 排除法:使用 Maven Helper,可以将冲突的Jar包在pom.xml中通过exclude来进行排除;

    • 版本锁定法:如果项目中依赖同一Jar包的很多版本,一个个排除非常麻烦,此时可用版本锁定法,即直接明确引入指定版本的依赖。此种方式的优先级最高。

    • 通过设置classpath指定jar包加载的先后顺序 

3.1Mavenhelper 解决冲突

  

  具体步骤:  

    1.使用mavenHelper 选择 Confilicts;

    2.如果列表存在冲突的依赖,则点击查看冲突的详情

    3.对冲突的依赖可进行右键;使用 exclude 进行排除即可解决冲突

3.2 通过设置 classpath 指定jar包加载的先后顺序

  第一种方式:
java -jar -classpath C:\dependency\framework.jar:C:\location\otherFramework.jar  test.jar

  第二种方式(-cp 等于 -classpath):

java -jar -cp C:\dependency\framework.jar:C:\location\otherFramework.jar  test.jar

  第三种方式:

-Djava.class.path=a.jar

  第四种方式:

-Xbootclasspath/a: 

  classpath 理解和设置可以查看这篇文章:Tomcat 与 JVM 中classpath的理解和设置总结

4.Maven管理机制

依赖传递原则

  当在Maven项目中引入A的依赖,A的依赖通常又会引入B的jar包,B可能还会引入C的jar包。这样,当你在pom.xml文件中添加了A的依赖,Maven会自动的帮你把所有相关的依赖都添加进来。

  如下图所示,项目 A 依赖于项目 B,B 又依赖于项目 C,此时 B 是 A 的直接依赖,C 是 A 的间接依赖。

 

  Maven 的依赖传递机制是指:不管 Maven 项目存在多少间接依赖,POM 中都只需要定义其直接依赖,不必定义任何间接依赖,Maven 会动读取当前项目各个直接依赖的 POM,将那些必要的间接依赖以传递性依赖的形式引入到当前项目中。Maven 的依赖传递机制能够帮助用户一定程度上简化 POM 的配置。

  基于 A、B、C 三者的依赖关系,根据 Maven 的依赖传递机制,我们只需要在项目 A 的 POM 中定义其直接依赖 B,在项目 B 的 POM 中定义其直接依赖 C,Maven 会解析 A 的直接依赖 B的 POM ,将间接依赖 C 以传递性依赖的形式引入到项目 A 中。

  即当一个依赖需要另外一个依赖支撑时,Maven会帮我们把相应的依赖依次添加到项目当中。这样的好处是,使用起来就非常方便,不用自己挨个去找依赖Jar包了。坏处是会引起Jar包冲突,

最短路径优先原则

  但当一个间接依赖存在多条引入路径时,为了避免出现依赖重复的问题,Maven 通过依赖调节来确定间接依赖的引入路径。

  依赖调节遵循以下两条原则:

    1. 引入路径短者优先

    2. 先声明者优先

  以上两条原则,优先使用第一条原则解决,第一条原则无法解决,再使用第二条原则解决。

引入路径短者优先

  引入路径短者优先,顾名思义,当一个间接依赖存在多条引入路径时,引入路径短的会被解析使用。

  例如,A 存在这样的依赖关系: A->B->C->D(1.0) A->X->D(2.0)

  D 是 A 的间接依赖,但两条引入路径上有两个不同的版本,很显然不能同时引入,否则造成重复依赖的问题。根据 Maven 依赖调节的第一个原则:引入路径短者优先,D(1.0)的路径长度为 3,D(2.0)的路径长度为 2,因此间接依赖 D(2.0)将从 A->X->D(2.0) 路径引入到 A 中。

先声明者优先

  先声明者优先,顾名思义,在引入路径长度相同的前提下,POM 文件中依赖声明的顺序决定了间接依赖会不会被解析使用,顺序靠前的优先使用。

  例如,A 存在以下依赖关系: A->B->D(1.0) A->X->D(2.0)

  D 是 A 的间接依赖,其两条引入路径的长度都是 2,此时 Maven 依赖调节的第一原则已经无法解决,需要使用第二原则:先声明者优先。

5.Tomcat启动时Jar包和类的加载顺序

最后,梳理一下Tomcat启动时,对Jar包和类的加载顺序,其中包含上面提到的不同种类的类加载器默认加载的目录:

  • $java_home/lib 目录下的java核心api;
  • $java_home/lib/ext 目录下的java扩展jar包;
  • java -classpath/-Djava.class.path所指的目录下的类与jar包;
  • $CATALINA_HOME/common目录下按照文件夹的顺序从上往下依次加载;
  • $CATALINA_HOME/server目录下按照文件夹的顺序从上往下依次加载;
  • $CATALINA_BASE/shared目录下按照文件夹的顺序从上往下依次加载;
  • 项目路径/WEB-INF/classes下的class文件;
  • 项目路径/WEB-INF/lib下的jar文件;

上述目录中,同一文件夹下的Jar包,按照顺序从上到下一次加载。如果一个class文件已经被加载到JVM中,后面相同的class文件就不会被加载了

 
 
 

Maven依赖冲突解决总结的更多相关文章

  1. Maven间接依赖冲突解决办法

    如果项目中maven依赖太多,由于还有jar之间的间接依赖,所以可能会存在依赖冲突.依赖冲突大部分都是由于版本冲突引起的,查看maven的依赖关系,可以找到引起冲突的间接依赖 如上图,通过Depend ...

  2. Maven 传递依赖冲突解决(了解)

    1 传递依赖冲突解决(了解) 传递依赖:A(项目)依赖B,B依赖C(1.1版本),B是A的直接依赖,C就是A的传递依赖 导入依赖D,D依赖C(1.2版本) 1.1 Maven自己调解原则 1.1.1  ...

  3. 解决maven依赖冲突问题

    解决maven依赖冲突问题 1.idea 安装maven helper插件 2.打开pom.xml文件 底部多出一个Dependency Analyzer选项 点开这个选项 找到冲突,点击右键,选择E ...

  4. 【核心】project(idea文件)、module(iml文件)到SSM集成、热部署、Tomcat启动、MAVEN依赖冲突

    http://wiki.jikexueyuan.com/project/intellij-idea-tutorial/project-composition-introduce.html 在 Inte ...

  5. 说说maven依赖冲突,依赖调解,依赖传递和依赖范围

    说maven依赖冲突之前需要先说说maven的 依赖传递. 依赖传递 当前项目引入了一个依赖,该依赖的依赖也会被引入项目.更加准确的说法是,maven会解析直接依赖的POM,将那些必要的间接依赖,以传 ...

  6. 封装jar问题java.lang.SecurityException: Invalid signature file digest for Manifest main attributes以及maven依赖重提解决

    1.jar包封装完成后,其他项目引用jar,启动时报错java.lang.SecurityException: Invalid signature file digest for Manifest m ...

  7. IDEA 解决 Maven 依赖冲突的高能神器,这一篇够不够?

    ​ 1.何为依赖冲突 Maven是个很好用的依赖管理工具,但是再好的东西也不是完美的.Maven的依赖机制会导致Jar包的冲突.举个例子,现在你的项目中,使用了两个Jar包,分别是A和B.现在A需要依 ...

  8. maven依赖冲突以及解决方法

    什么是依赖冲突 依赖冲突是指项目依赖的某一个jar包,有多个不同的版本,因而造成类包版本冲突 依赖冲突的原因 依赖冲突很经常是类包之间的间接依赖引起的.每个显式声明的类包都会依赖于一些其它的隐式类包, ...

  9. 解决maven依赖冲突,这篇就够了!

    一.前言 什么是依赖冲突 依赖冲突是指项目依赖的某一个jar包,有多个不同的版本,因而造成了包版本冲突. 依赖冲突的原因 我们在maven项目的pom中 一般会引用许许多多的dependency.例如 ...

  10. 如何快速的解决Maven依赖冲突

    为什么会出现依赖冲突 首先要说明Maven的依赖管理,具体的可以参考这边 Maven学习——依赖管理 这篇文章,maven在依赖冲管理中有一下几个原则. 依赖是使用Maven坐标来定位的,而Maven ...

随机推荐

  1. 让 Serverless 更普惠,阿里云函数计算 FC 宣布全面降价,最大幅度达 37.5%

    11月5日,2022 杭州 · 云栖大会上,阿里云宣布函数计算 FC 开启全面降价,vCPU 单价降幅** 11%,其他的各个独立计费项最高降幅达 37.5%**. 本次云栖大会上,阿里云智能总裁张建 ...

  2. netty系列之:在netty中使用proxy protocol

    目录 简介 netty对proxy protocol协议的支持 HAProxyMessage的编码解码器 netty中proxy protocol的代码示例 总结 简介 我们知道proxy proto ...

  3. 交叉编译GDB

    PC主机安装必要软件 sudo apt-get install bison flex expect-dev build-essential m4 autoconf automake texi2html ...

  4. python选课系统项目详解

    选课系统项目详解 选课系统简介及分析 选课系统架构设计分析 选课系统目录设计 管理员视图 注册 登录 创建学校 创建课程 创建讲师 学生视图 注册 登录 选择学校 选择课程 查看分数 教师视图 登录 ...

  5. Windows机器下VSCode安装及使用CmakeLists编译工程demo

    使用VSCode, Mingw and Cmake写工程代码,从零开始写的那种,全过程分享...... 你若发现该帖中有待商榷的地方,还请指正赐教,先行拜谢了! 1 软件下载 1.1 vscode下载 ...

  6. MyEclipse反编译插件安装于使用

    在MyEclipse开发中,使用反编译插件可以对jar包的源码进行随机的查看,节约了使用jd-gui查看时间. 百度云分享地址:链接:https://pan.baidu.com/s/1efNR6A 密 ...

  7. DHorse操作手册

    在介绍DHorse的操作之前,我们先来看一下发布一个系统的流程是什么样的. 发布系统的流程 我们以一个Springboot系统为例,来说明一下发布流程. 1.首先从代码仓库下载代码,比如Gitlab: ...

  8. 【每日一题】【动态规划】2022年1月30日-NC127 最长公共子串

    描述 给定两个字符串str1和str2,输出两个字符串的最长公共子串 题目保证str1和str2的最长公共子串存在且唯一. 方法1:dp数组存子串 import java.util.*; public ...

  9. 关于Window中右键新建菜单的设置

    在日常工作中,有时候需要根据自己的需要对Windows桌面右键新建菜单进行自定义,自定义的方法如下: 1.在Window中输入Win+R调出运行命令框 2.输入regedit,打开注册表 3.如果想要 ...

  10. 《HTTP权威指南》– 7.缓存

    Web缓存的概念 Web缓存是可以自动保存常见文档副本的HTTP设备. 使用缓存的优点: 减少了数据的数据传输,节省了网络费用: 缓解了网络瓶颈的问题,不需要更多的带宽就能更快地加载页面: 降低了原始 ...