Maven依赖冲突解决总结
转载请注明出处:
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 通过依赖调节来确定间接依赖的引入路径。
依赖调节遵循以下两条原则:
引入路径短者优先
先声明者优先
引入路径短者优先
引入路径短者优先,顾名思义,当一个间接依赖存在多条引入路径时,引入路径短的会被解析使用。
例如,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依赖冲突解决总结的更多相关文章
- Maven间接依赖冲突解决办法
如果项目中maven依赖太多,由于还有jar之间的间接依赖,所以可能会存在依赖冲突.依赖冲突大部分都是由于版本冲突引起的,查看maven的依赖关系,可以找到引起冲突的间接依赖 如上图,通过Depend ...
- Maven 传递依赖冲突解决(了解)
1 传递依赖冲突解决(了解) 传递依赖:A(项目)依赖B,B依赖C(1.1版本),B是A的直接依赖,C就是A的传递依赖 导入依赖D,D依赖C(1.2版本) 1.1 Maven自己调解原则 1.1.1 ...
- 解决maven依赖冲突问题
解决maven依赖冲突问题 1.idea 安装maven helper插件 2.打开pom.xml文件 底部多出一个Dependency Analyzer选项 点开这个选项 找到冲突,点击右键,选择E ...
- 【核心】project(idea文件)、module(iml文件)到SSM集成、热部署、Tomcat启动、MAVEN依赖冲突
http://wiki.jikexueyuan.com/project/intellij-idea-tutorial/project-composition-introduce.html 在 Inte ...
- 说说maven依赖冲突,依赖调解,依赖传递和依赖范围
说maven依赖冲突之前需要先说说maven的 依赖传递. 依赖传递 当前项目引入了一个依赖,该依赖的依赖也会被引入项目.更加准确的说法是,maven会解析直接依赖的POM,将那些必要的间接依赖,以传 ...
- 封装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 ...
- IDEA 解决 Maven 依赖冲突的高能神器,这一篇够不够?
1.何为依赖冲突 Maven是个很好用的依赖管理工具,但是再好的东西也不是完美的.Maven的依赖机制会导致Jar包的冲突.举个例子,现在你的项目中,使用了两个Jar包,分别是A和B.现在A需要依 ...
- maven依赖冲突以及解决方法
什么是依赖冲突 依赖冲突是指项目依赖的某一个jar包,有多个不同的版本,因而造成类包版本冲突 依赖冲突的原因 依赖冲突很经常是类包之间的间接依赖引起的.每个显式声明的类包都会依赖于一些其它的隐式类包, ...
- 解决maven依赖冲突,这篇就够了!
一.前言 什么是依赖冲突 依赖冲突是指项目依赖的某一个jar包,有多个不同的版本,因而造成了包版本冲突. 依赖冲突的原因 我们在maven项目的pom中 一般会引用许许多多的dependency.例如 ...
- 如何快速的解决Maven依赖冲突
为什么会出现依赖冲突 首先要说明Maven的依赖管理,具体的可以参考这边 Maven学习——依赖管理 这篇文章,maven在依赖冲管理中有一下几个原则. 依赖是使用Maven坐标来定位的,而Maven ...
随机推荐
- 【Java并发002】使用级别:线程同步与线程通信
一.前言 本文介绍Java多线程技术,分为五个部分:多线程的两种实现方式--继承Thread类和实现Runnable接口:线程同步应用:三人吃苹果:线程同步+线程通信应用之一:生产者-消费者问题:线程 ...
- 第2-3-7章 个人网盘服务接口开发-文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss
目录 5.8 导入其他接口代码 5.8.1 接口导入-分页查询附件 5.8.2 接口导入-根据业务类型/业务id查询附件 5.9 导入网盘服务接口 5.9.1 导入FileController 5.9 ...
- Spring Security(1)
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 虽然说互联网是一个非常开发.几乎没有边界的信息大海,但说起来有点奇怪的是,每个稍微有点规模的互联网应用都有自己的权限系统,而权限的本质却是是封闭 ...
- 万字 HashMap 详解,基础(优雅)永不过时
本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 前言 大家好,我是小彭. 在上一篇文章里,我们聊到了散列表的整体设计思想,在后续几篇文章里,我们将以 Jav ...
- 进军东南亚市场,腾讯云数据库 TDSQL 助力印尼 BNC 银行数字化转型
腾讯云数据库在助力金融核心系统分布式替换上,已经辐射到了东南亚市场. 东南亚最大的银行之一印尼BNC银行(Bank Neo Commerce)已正式完成新核心分布式迁移,使用腾讯云数据库TDSQL后, ...
- 【SQL进阶】Day05:窗口函数
〇.概述 一.专用窗口函数 1.每类试卷得分前3名 自己写出来的部分 SELECT tag AS tid, uid AS uid, Rank AS ranking -- 如何确定排名 FROM exa ...
- 【Hadoop学习】中:HDFS、shell操作、客户端API操作、数据流、1NN、2NN原理、DataNode配置
一.概述 1.背景.定义.使用场景(一次写入.不支持修改) 2.优(容错)缺点(延迟.不支持小文件.不支持修改) 3.组成架构 NameNode:Master,管理命名空间.配置策略 DataNode ...
- 【Scala复习】基础知识、函数式编程、面向对象、集合、隐式转换、模式匹配、泛型
重点版 详细版 基础知识常量和变量尽量使用常量val别使用变量var变量的命名数字字母下划线_特殊的用法数据类型java基本数据类型引用数据类型scalaAny-对象的根类AnyVal-数值类型Lon ...
- 金融科技 DevOps 的最佳实践
随着软件技术的发展,越来越多的企业已经开始意识到 DevOps 文化的重要价值.DevOps 能够消除改变公司业务开展方式,并以更快的速度实现交付,同时创建迭代反馈循环以实现持续改进.而对于金融科技( ...
- 手动解析word Table模块内容
最近来了一个需求, 需要手动解析word ( 好处就是不需要安装office 以及不会有office解析的线程残留),然后就是可以自定义解析规则,比较方便 比如解析这个word里面的内容: 标题,表格 ...