Maven类包冲突终极三大解决技巧 mvn dependency:tree

2023-05-16

举例
A依赖于B及C,而B又依赖于X、Y,而C依赖于X、M,则A除引B及C的依赖包下,还会引入X,Y,M的依赖包(一般情况下了,Maven可通过<scope>等若干种方式控制传递依赖)。
这里有一个需要特别注意的,即B和C同时依赖于X,假设B依赖于X的1.0版本,而C依赖于X的2.0版本,A究竟依赖于X的1.0还是2.0版本呢?
这就看Classloader的加载顺序了,假设Classloader先加载X_1.0,而它就不会再加载X_2.0了,如果A恰恰希望使用X_2.0呢,血案就这样不期而遇了。

三大技巧
第一板斧:找到传递依赖的鬼出在哪里?

dependency:tree是把照妖照,pom.xml用它照照,所有传递性依赖都将无处遁形,并且会以层级树方式展现,非常直观。

以下就是执行dependency:tree后的一个输出:
引用

[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ euler-foundation ---
[INFO] com.hsit:euler-foundation:jar:0.9.0.1-SNAPSHOT
[INFO] +- com.rop:rop:jar:1.0.1:compile
[INFO] |  +- org.slf4j:slf4j-api:jar:1.7.5:compile
[INFO] |  +- org.slf4j:slf4j-log4j12:jar:1.7.5:compile
[INFO] |  +- log4j:log4j:jar:1.2.16:compile
[INFO] |  +- commons-lang:commons-lang:jar:2.6:compile
[INFO] |  +- commons-codec:commons-codec:jar:1.6:compile
[INFO] |  +- javax.validation:validation-api:jar:1.0.0.GA:compile
[INFO] |  +- org.hibernate:hibernate-validator:jar:4.2.0.Final:compile
[INFO] |  +- org.codehaus.jackson:jackson-core-asl:jar:1.9.5:compile
[INFO] |  +- org.codehaus.jackson:jackson-mapper-asl:jar:1.9.5:compile
[INFO] |  +- org.codehaus.jackson:jackson-jaxrs:jar:1.9.5:compile
[INFO] |  +- org.codehaus.jackson:jackson-xc:jar:1.9.5:compile
[INFO] |  \- com.fasterxml.jackson.dataformat:jackson-dataformat-xml:jar:2.2.3:compile
[INFO] |     +- com.fasterxml.jackson.core:jackson-core:jar:2.2.3:compile
[INFO] |     +- com.fasterxml.jackson.core:jackson-annotations:jar:2.2.3:compile
[INFO] |     +- com.fasterxml.jackson.core:jackson-databind:jar:2.2.3:compile
[INFO] |     +- com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:2.2.3:compile
[INFO] |     \- org.codehaus.woodstox:stax2-api:jar:3.1.1:compile
[INFO] |        \- javax.xml.stream:stax-api:jar:1.0-2:compile


刚才吹嘘dependency:tree时,我用到了“无处遁形”,其实有时你会发现简单地用dependency:tree往往并不能查看到所有的传递依赖。不过如果你真的想要看所有的,必须得加一个-Dverbose参数,这时就必定是最全的了。
全是全了,但显示出来的东西太多,头晕目眩,有没有好法呢?当然有了,加上Dincludes或者Dexcludes说出你喜欢或讨厌,dependency:tree就会帮你过滤出来:
引用
Dincludes=org.springframework:spring-tx
过滤串使用groupId:artifactId:version的方式进行过滤,可以不写全啦,如:

mvn dependency:tree -Dverbose -Dincludes=asm:asm  

就会出来asm依赖包的分析信息:

[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ ridge-test ---
[INFO] com.ridge:ridge-test:jar:1.0.2-SNAPSHOT
[INFO] +- asm:asm:jar:3.2:compile
[INFO] \- org.unitils:unitils-dbmaintainer:jar:3.3:compile
[INFO]    \- org.hibernate:hibernate:jar:3.2.5.ga:compile
[INFO]       +- cglib:cglib:jar:2.1_3:compile
[INFO]       |  \- (asm:asm:jar:1.5.3:compile - omitted for conflict with 3.2)
[INFO]       \- (asm:asm:jar:1.5.3:compile - omitted for conflict with 3.2)
[INFO] ------------------------------------------------------------------------

对asm有依赖有一个直接的依赖(asm:asm:jar:3.2)还有一个传递进入的依赖(asm:asm:jar:1.5.3)

第二板斧:将不想要的传递依赖剪除掉

承上,假设我们不希望asm:asm:jar:1.5.3出现,根据分析,我们知道它是经由org.unitils:unitils-dbmaintainer:jar:3.3引入的,那么在pom.xml中找到这个依赖,做其它的调整:

    <dependency>  
        <groupId>org.unitils</groupId>  
        <artifactId>unitils-dbmaintainer</artifactId>  
        <version>${unitils.version}</version>  
        <exclusions>  
            <exclusion>  
                <artifactId>dbunit</artifactId>  
                <groupId>org.dbunit</groupId>  
            </exclusion>  
            <!-- 这个就是我们要加的片断 -->  
            <exclusion>  
                <artifactId>asm</artifactId>  
                <groupId>asm</groupId>  
            </exclusion>  
        </exclusions>  
    </dependency>  


再分析一下,你可以看到传递依赖没有了:


    [INFO]  
    [INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ ridge-test ---  
    [INFO] com.ridge:ridge-test:jar:1.0.2-SNAPSHOT  
    [INFO] \- asm:asm:jar:3.2:compile  
    [INFO] ------------------------------------------------------------------------  
    [INFO] BUILD SUCCESS  



第三板斧:查看运行期类来源的JAR包

有时,你以为解决了,但是偏偏还是报类包冲突(典型症状是java.lang.ClassNotFoundException或Method不兼容等异常),这时你可以设置一个断点,在断点处通过下面这个我做的工具类来查看Class所来源的JAR包:

    package com.ridge.util;  
      
    import java.io.File;  
    import java.net.MalformedURLException;  
    import java.net.URL;  
    import java.security.CodeSource;  
    import java.security.ProtectionDomain;  
      
    /** 
     * @author : chenxh 
     * @date: 13-10-31 
     */  
    public class ClassLocationUtils {  
      
        /** 
         * 获取类所有的路径 
         * @param cls 
         * @return 
         */  
        public static String where(final Class cls) {  
            if (cls == null)throw new IllegalArgumentException("null input: cls");  
            URL result = null;  
            final String clsAsResource = cls.getName().replace('.', '/').concat(".class");  
            final ProtectionDomain pd = cls.getProtectionDomain();  
            if (pd != null) {  
                final CodeSource cs = pd.getCodeSource();  
                if (cs != null) result = cs.getLocation();  
                if (result != null) {  
                    if ("file".equals(result.getProtocol())) {  
                        try {  
                            if (result.toExternalForm().endsWith(".jar") ||  
                                    result.toExternalForm().endsWith(".zip"))  
                                result = new URL("jar:".concat(result.toExternalForm())  
                                        .concat("!/").concat(clsAsResource));  
                            else if (new File(result.getFile()).isDirectory())  
                                result = new URL(result, clsAsResource);  
                        }  
                        catch (MalformedURLException ignore) {}  
                    }  
                }  
            }  
            if (result == null) {  
                final ClassLoader clsLoader = cls.getClassLoader();  
                result = clsLoader != null ?  
                        clsLoader.getResource(clsAsResource) :  
                        ClassLoader.getSystemResource(clsAsResource);  
            }  
            return result.toString();  
        }  
      
    }  


随便写一个测试,设置好断点,在执行到断点处按alt+F8动态执行代码(intelij idea),假设我们输入:
Java代码  收藏代码

ClassLocationUtils.where(org.objectweb.asm.ClassVisitor.class)  

即可马上查出类对应的JAR了:

这就是org.objectweb.asm.ClassVisitor类在运行期对应的JAR包,如果这个JAR包版本不是你期望你,就说明是你的IDE缓存造成的,这时建议你Reimport一下maven列表就可以了,如下所示(idea):

Reimport一下,IDE会强制根据新的pom.xml设置重新分析并加载依赖类包,以得到和pom.xml设置相同的依赖。(这一步非常重要哦,经常项目组pom.xml是相同的,但是就是有些人可以运行,有些人不能运行,俗称人品问题,其实都是IDE的缓存造成的了
idea清除缓存,为了提高效率不建议采用reimport重新起开启项目的方式,建议采用idea自带的功能,File->Invalidate Caches 功能直接完成清除idea cache
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Maven类包冲突终极三大解决技巧 mvn dependency:tree 的相关文章

  • Ubuntu使用apt-get安装本地deb包

    Ubuntu使用apt get安装本地deb包 milantgh 博客园
  • 随遇而安也是一种选择

    随遇而安也是一种选择 故事的开头都是相似的 xff0c 故事的结尾各有各的传奇 xff0c 各有各的平凡 题记 高中的岁月总是让人难忘的 xff0c 菁菁岁月中的庆阳一中 xff0c 充满了书生意气的神采飞扬 xff0c 恩师与同窗 xff
  • OFDPA软件概述

    OFDPA软件概述 OF DPA xff08 openflow data plane abstraction xff09 是一个应用软件组件 实现了 openflow与broadcom SDK间适配层的功能 OF DPA在broadcom交
  • freertos和ucos的区别

    一 freeRTOS比uCOS II优胜的地方 xff1a 1 内核ROM和耗费RAM都比uCOS 小 xff0c 特别是RAM 这在单片机里面是稀缺资源 xff0c uCOS至少要5K以上 xff0c 而freeOS用2 3K也可以跑的很
  • wget和curl中使用代理

    命令使用代理 wget curl 都支持使用代理 wget e http proxy 61 10 1 4 43 8080 proxy mimvp com curl x 10 1 4 43 8080 proxy mimvp com 环境变量使
  • SQL 触发器与WebApi回执

    1 需求数据库表添加 xff0c 修改 xff0c 删除数据 xff0c 触发器生效 xff0c 推送数据数据到WCF接口 a 创建WCF服务 xff0c 发布服务 b 启用数据库CLR功能 xff0c 默认是关闭状态 EXEC sp co
  • inelliJ IDEA注册码

    http idea lanyus com
  • 正则表达式之?、(?:pattern)、(?!pattern)、(?=pattern)理解及应用

    今天朋友问我一个问题 xff0c 是这样子的 xff0c 通过正则表达式匹配html标签input包含hidden的字符串 xff0c 具体如下 xff1a 34 lt input type 61 34 hidden 34 id 61 34
  • cmake源码安装

    Data 2017 12 1 Author cjh Theme cmake源码安装 在玩TI AM5728时 xff0c 要用到cmake编译程序 xff0c 无奈开发板又不能用apt get只好自己源码安装了 cmake源码下载 解压源码
  • Ubuntu下逻辑坏道解决方案

    一 逻辑坏道修复方法 逻辑坏道 服务器硬盘相比其他部件是较容易坏的 xff0c 如突然断电 大量频繁写入都会加速硬盘的老化 xff0c 下面介绍一些判断硬盘状况和修复的方法 发现硬盘坏道 dmesg 当有硬盘坏道时 xff0c 通常在dme
  • 解决本地无法ssh连接ubuntu虚拟机

    1 保证双方都能互相ping通 本地 Windows 查看ip xff1a ipconfig ubuntu虚拟机查看ip span class token function ifconfig span 2 保证ubuntu虚拟机安装了ssh
  • 70、在js中为什么0.1+0.2不等于0.3

    并不是所有小数都可以用 完整 的二进制来表示的 xff0c 比如十进制 0 1 在转换成二进制小数的时候 xff0c 是一串无限循环的二进制数 xff0c 计算机是无法表达无限循环的二进制数的 xff0c 毕竟计算机的资源是有限 因此 xf
  • Outlook 2013/2016 显示“正在启动...“ 无法进入Outlook的解决方案

    因上次非正常关闭 xff0c 导致Outlook 2016启动时 xff0c 一直处于启动界面 xff0c 无法进入主界面正常工作 刚开始Outlook 2016启动界面显示的是 34 正在处理 34 查询网上各种方法 xff0c 安全启动
  • H265 CTU、CU、PU、TU划分的特点及要求

    目录 H265 CTU CU PU TU划分的特点及要求大小及划分模式常见问题1 Spec里对于CTU大小的规定在哪 xff1f 2 Spec对于TU大小的规定在哪 xff1f 3 Spec里对于M 2 M 2的划分方式的规定在哪里 xff
  • Oracle VM VirtualBox虚拟机使用问题总结

    我本机的配置是Ubuntu 18 04 43 Oracle VM VirtualBox虚拟机 6 1 12 43 虚拟win7操作系统 xff0c 对虚拟机了解甚少 xff0c 以下仅为一些实践中的经验 xff1a 一 升级后屏幕分辨率问题
  • C语言中string函数详解

    PS xff1a 本文包含了大部分strings函数的说明 xff0c 并附带举例说明 本来想自己整理一下的 xff0c 发现已经有前辈整理过了 xff0c 就转了过来 修改了原文一些源码的问题 xff0c 主要是用char 字义字符串的问
  • MP3的帧结构

    原文地址 xff1a http www eefocus com jjbearustc blog 07 09 3716 3e901 html MP3帧包括以下4个部分 xff1a 1 帧头 xff1a 比特流中包含同步和状态信息的部分 2 错
  • git am PATCH 失败的处理方法

    参考 xff1a http www cnblogs com domainfei articles 2433504 html http blog sina com cn s blog 5372b1a301015y0n html 英文原文地址
  • AAC帧格式及编码介绍

    参考资料 xff1a AAC以adts格式封装的分析 xff1a http wenku baidu com view 45c755fd910ef12d2af9e74c html aac编码介绍 xff1a http wenku baidu
  • 基于ubuntu14.04的Mobilenet_SSD环境搭建

    Data 2017 11 22 Author cjh Theme 基于ubuntu14 04的Mobilenet SSD环境搭建 Caffe for SSD xff1a https github com weiliu89 caffe tre

随机推荐

  • [open vSwitch]查看OVS端口ofport编号及对应虚拟机MAC

    在用open vSwitch做实验时 xff0c 我们经常需要知道OVS port对应的ofport编号 xff0c 这个比较容易 xff0c 用 ovs ofctl show bridge 就能得到 如 root 64 vaio ovs
  • 4、基于51单片机智能语音识别小车控制 语音口令说话控制系统设计

    毕设帮助 开题指导 技术解答 xff08 有偿 xff09 见文末 目录 摘要 一 硬件方案 二 设计功能 三 实物图 四 原理图 五 PCB图 六 程序源码 七 资料包括 摘要 随着电子工业的发展 xff0c 具有语音控制功能的小车越来越
  • H264中的SPS、PPS提取与作用

    牛逼的视频会议网站 xff1a http wmnmtm blog 163 com blog m 61 0 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 4
  • Linux系统备份与还原

    在 使用Ubuntu之前 xff0c 相信很多人都有过使用Windows系统的经历 如果你备份过Windows系统 xff0c 那么你一定记忆犹新 xff1a 首先需要找到一个备份工 具 通常都是私有软件 xff0c 然后重启电脑进入备份工
  • ip能ping开但是不能远程登陆

    刚刚安装ftp时玩将防火墙开启了 然后退出ssh再登陆时就登陆不上去了 出现 xff1a ip能ping开但是不能远程登陆 xff1b telnet ip 也不通 以为使系统问题 xff0c 但是想想刚刚的操作还是防火墙 解决方法 xff1
  • 如何检索CPCI-S

    1 打开Web of Science www webofknowledge com 2 选择数据库大类 xff1a Web of Science核心合集 xff1b 3 会议论文 xff0c 需要选择web of science数据库中的一
  • ZeroMQ消息传输协议 (v2.0)

    因为项目上在和其他团队联调时需要抓包分析消息正确性的问题 xff0c 因此在网络上查找了一下关于ZeroMQ的协议资料 找到如下文章 原文 另外这里有一篇对ZeroMQ实现讲的比较深的文章 xff0c 有兴趣也可以看看 xff1a 全网仅此
  • mysql左右匹配原则的用法和理解

    重点 xff1a mysql的最左匹配原则其实是和where后面的查询条件顺序是没有关系的只和索引的字段顺序有关 xff1b xff08 这里说的顺序是联合索引的顺序 xff09 这点网上很多地方都说错了 下面我们来用代码模拟一下问题 这里
  • 如何做好项目经理

    我一直赞同这个观点 xff1a 项目经理是干出来的 xff0c 不是学出来的 xff1b 是带出来的 xff0c 不是教出来的 一个人要成长为一名合格的项目经理主要不是靠学 xff0c 而是靠干 xff0c 当然学也很重要 靠干 xff0c
  • Javascript进制转换

    介绍一个简单的用Javascript进行 进制 转换的方式 xff1a 将十进制转换为十六进制 xff1a var i 61 10 alert parseInt 10 10 toString 16 同样 xff0c 将十六进制转换为十进制
  • js实现进制变换 10->16

    进制变换 10 gt 16 function heTransform data var pattern 61 new RegExp 39 1 9 d 0 39 判断是否是10进制数字 if pattern test data var hex
  • 用Visual C#实现局域网点对点通讯

    用Visual C xff03 实现局域网点对点通讯 作者 xff1a 马金虎 日期 xff1a 2003 9 28 出处 xff1a P2P中国 PPcn net 点对点即Peer To Peer xff0c 通常简写为P2P 所谓网络中
  • Makefile学习总结

    Data 2017 12 07 Author cjh Theme Makefile Tutorial 俗话说 xff0c 工欲善其事必先利其器 xff0c 所以我们先来介绍一下Makefile中的特殊字符 64 表示目标文件 表示所有的依赖
  • stmdb和ldmia

    stmdb xff1a db xff08 decrease before xff09 表示先减后存 指令 stmdb sp fp ip lr pc 34 表示sp等于最终被修改的sp的值 假设 sp 61 4096 xff0c 此条指令的执
  • ros之tf经验总结

    1 概念 搞ros都离不开tf xff0c 当建立一个机器人模型时 xff0c 第一步就是要确定机器人的tf结构 以kobuki导航运行为例 xff0c 首先是 map xff1a 地图坐标 xff0c 固定坐标系 odom xff1a 机
  • setInterval和setTimeout的缺陷和优势分析

    先把问题摆出来 xff1a 使用定时器的setInterval xff08 xff09 方法会出现程序并不是按照我们设定的精确时间而调用的问题 xff01 定时器 xff1a 在JavaScript中经常会使用定时器来进行延时或者是重复调用
  • 关于KEIL调试时CortexJLink中SW Device检测不到芯片解决办法

    使用Jlink第一次下载成功后 xff0c 第二次检测不到设备 xff0c 极大原因是因为软件配置了SWDIO和SWCLK的状态导致的 解决办法 xff1a 软件中将配置两个引脚状态程序注释 xff0c 将芯片的BOOT0引脚接高电平 xf
  • Web大规模高并发请求和抢购的解决方案

    电商的秒杀和抢购 xff0c 对我们来说 xff0c 都不是一个陌生的东西 然而 xff0c 从技术的角度来说 xff0c 这对于Web系统是一个巨大的考验 当一个Web系统 xff0c 在一秒钟内收到数以万计甚至更多请求时 xff0c 系
  • Java用自定义的类作为HashMap的key值

    这是Java中很经典的问题 xff0c 在面试中也经常被问起 其实很多书或者文章都提到过要重载hashCode 和equals 两个方法才能实现自定义键在HashMap中的查找 xff0c 但是为什么要这样以及如果不这样做会产生什么后果 x
  • Maven类包冲突终极三大解决技巧 mvn dependency:tree

    举例 A依赖于B及C xff0c 而B又依赖于X Y xff0c 而C依赖于X M xff0c 则A除引B及C的依赖包下 xff0c 还会引入X xff0c Y xff0c M的依赖包 xff08 一般情况下了 xff0c Maven可通过