【异常解决】为什么会产生jar包冲突,如何排查jar包冲突?

简介: 【异常解决】为什么会产生jar包冲突,如何排查jar包冲突?

在实际开发中,很多项目经常会使用 Maven 进行包管理。在 poml 文件中进行包依赖时,常存在引入一个 jar 包中默认依赖了其他的 jar 包的情况。这样很容易导致 jar 包冲突,从而产生一些诡异问题,如版本问题导致的类、方法找不到等。下面我们将聊聊具体关于依赖冲突产生的原因、排查方式以及解决的方案。

一、Jar包产生冲突的原因

我们知道 maven 有传递性依赖机制,举例来说,当我们需要依赖 A 的时候,就会在 pom.xml 中引入 A 的 jar 包;而 A 的 jar 包中依赖了 B 的 jar 包,这样 Maven 在解析 pom.xml 的时候,会依次将  A、B  的 jar包全部都引入进来。

比如:

A --> B --> C --> mapstruct 1.2.0(mapstruct 1.2.0)

E --> F --> G --> mapstruct 1.3.0(mapstruct 1.3.0)

这样就会造成一个问题:

假设 pom.xml 文件中引入 A 与 E 两个依赖,按照上述的传递性依赖机制,与默认的依赖调解机制(第一:路径最近者优先;第二:第一声明优先),默认引用的是 mapstruct 1.2.0 版本的jar包,mapstruct 1.3.0 的jar包不会被引用。引用路径相同,则会开启第二个机制(第一声明优先)。

如果 G 的 methodG 使用了新版本 mapstruct 1.3.0 才拥有的新类/新方法,程序中调用了 G 对应 mapstruct 1.3.0 的新类/新方法时,因为项目中引用的是 mapstruct 1.2.0,所以JVM去加载 Class 时就会发现 mapstruct 1.2.0 没有这个类,就会抛出 ClassNotFoundException;同样,调用mapstruct 1.2.0没有的新方法时会抛出 NoSuchMethodError。

二、排查Jar包冲突的方式

我们可以借助一些插件工具帮助找出冲突jar的具体位置。下面分享一下我在项目中排查并解决包冲突的两种方式。

  • Maven Helper 插件
  • maven-enforcer-plugin 插件
  • maven命令行

2.1 Maven Helper 插件

一般来说,使用IDEA插件是一个简便的排查方法

下载 Maven Helper,如何下载,可以去查看我的另一篇文章:【IntelliJ IDEA插件】值得推荐的Idea几十大优秀插件、神级超级牛逼插件推荐(自用,真的超级牛逼)

打开要查找冲突的 pom.xml

点击 Dependency Analyzer 窗口一目了然

2.2 maven-enforcer-plugin插件

Maven提供了Maven-Enforcer-Plugin插件 , 用来校验约定遵守情况,比依赖 jar 包的版本等等。当规则检查不通过的时候则会构建失败。

1、在pom.xml中引入该插件

rules内则是定义校验规则,通过配置<dependencyConvergence/>可实现重复依赖检测。也支持自定义做一些其他检验如版本检验等。关于maven-enforcer-plugin插件rules的其他配置用法,感兴趣的朋友们,可以去查阅其相关的资料。

<rules>
  <requireMavenVersion>
    <version>3.0.4</version>
  </requireMavenVersion>
  <!--要求JDK版本)-->
  <requireJavaVersion>
    <version>6.0</version>
  </requireJavaVersion>
  <bannedDependencies>
    <!--是否检查传递性依赖(间接依赖)-->
    <searchTransitive>true</searchTransitive>
    <excludes>
      <exclude>junit:junit</exclude>
    </excludes>
    <message>must use TestNG</message>
  </bannedDependencies>
</rules>

2、配置好插件后进行项目构建,当存在包冲突时会在console中打印出来。

3、依据信息便可将不需要的jar包通过<exclusion>排除掉。

2.3 maven命令行

通过Maven命名行的方式也是也不错的选择:

  1. 通过 mvn dependency:tree 可以在控制台上打印出依赖
  2. 通过 mvn dependency:tree -Dverbose -Dincludes=groupId:artifactId 只打印出你关心的Jar包的依赖关系
  3. 通过标签手动排除依赖

例如:

<!-- 内部引用 -->
<dependency>
  <groupId>com.iot.brain.platform</groupId>
  <artifactId>back-brain-platform-business</artifactId>
  <version>1.0-SNAPSHOT</version>
  <exclusions>
    <exclusion>
      <groupId>org.mapstruct</groupId>
      <artifactId>mapstruct</artifactId>
    </exclusion>
  </exclusions>
</dependency>

在引用guava时将com.google.errorprone这个包排除掉。

当然也有一些其他方法,对我来说第一种已经满足日常使用了。

三、避免Jar包冲突

最重要的还是要主动避免jar包冲突的情况,在父pom文件中利用 ,对依赖Jar包进行统一版本管理,一劳永逸。通常的做法是,在parent模块的pom文件中尽可能地声明所有相关依赖Jar包的版本,并在子pom中简单引用该构件即可。

例如在父pom文件中定义lombok的版本:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>
    </dependencies>
</dependencyManagement>

然后在子moudle中:

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

子moudle中自动会引用版本为1.18.10的lombok Jar包。

四、总结

关于依赖冲突解决方式有三种:最短路径原则、声明优先原则、依赖排除。在没有手动进行依赖排除的情况下,会依据最短路径原则、声明优先原则来选择jar包。关于依赖冲突排查可借助如maven-enforcer-plugin 与Maven Helper 插件。根据实际情况及环境,选择组合最优的解决方案解决依赖冲突问题。

完结!


相关文章
|
6月前
|
Java Maven
maven依赖原则以及jar包冲突
该文介绍了Maven依赖原则:最短路径优先,申明顺序优先和覆写优先。当有冲突时,Maven选择路径最短的版本,按POM中声明顺序加载,并且子POM的依赖优先于父POM。解决冲突最佳方式是通过`mvn dependency:tree`检查依赖树并调整POM文件中的坐标顺序。
132 2
|
6月前
|
Java Maven 数据安全/隐私保护
maven发布jar包到私服以及从私服下载jar包的操作
maven发布jar包到私服以及从私服下载jar包的操作
610 0
|
1月前
|
Java Windows
如何在windows上运行jar包/JAR文件 如何在cmd上运行 jar包 保姆级教程 超详细
本文提供了一个详细的教程,解释了如何在Windows操作系统的命令提示符(cmd)中运行JAR文件。
833 1
|
3月前
|
Java Maven 容器
Maven使用IDEA自带工具打包,同时将lib下的jar包打入,双击jar包可直接运行
使用IntelliJ IDEA的Artifacts功能,可以将项目依赖的第三方jar包打包进jar文件中,实现双击jar包即可直接运行。
Maven使用IDEA自带工具打包,同时将lib下的jar包打入,双击jar包可直接运行
|
3月前
|
SQL 前端开发 Java
在IDEA中使用Maven将SpringBoot项目打成jar包、同时运行打成的jar包(前后端项目分离)
这篇文章介绍了如何在IntelliJ IDEA中使用Maven将Spring Boot项目打包成可运行的jar包,并提供了运行jar包的方法。同时,还讨论了如何解决jar包冲突问题,并提供了在IDEA中同时启动Vue前端项目和Spring Boot后端项目的步骤。
在IDEA中使用Maven将SpringBoot项目打成jar包、同时运行打成的jar包(前后端项目分离)
|
3月前
|
Java Maven C++
【Azure Developer】记录一次使用Java Azure Key Vault Secret示例代码生成的Jar包,单独运行出现 no main manifest attribute, in target/demo-1.0-SNAPSHOT.jar 错误消息
【Azure Developer】记录一次使用Java Azure Key Vault Secret示例代码生成的Jar包,单独运行出现 no main manifest attribute, in target/demo-1.0-SNAPSHOT.jar 错误消息
|
3月前
|
Java Maven Windows
Maven 引用jar包冲突 Intellij 查找排除JAR包的依赖关系(Maven Helper)
Maven 引用jar包冲突 Intellij 查找排除JAR包的依赖关系(Maven Helper)
53 0
|
6月前
|
Java 应用服务中间件 数据库连接
hibernate+struts2整合jar包冲突
hibernate+struts2整合jar包冲突
|
6月前
|
Oracle 关系型数据库 Java
Flink CDC产品常见问题之Flink CDC 使用jar包启动异常如何解决
Flink CDC(Change Data Capture)是一个基于Apache Flink的实时数据变更捕获库,用于实现数据库的实时同步和变更流的处理;在本汇总中,我们组织了关于Flink CDC产品在实践中用户经常提出的问题及其解答,目的是辅助用户更好地理解和应用这一技术,优化实时数据处理流程。
|
6月前
|
Java 应用服务中间件
完美解决tomcat启动异常:Invalid byte tag in constant pool: 19;Unable to process Jar entry [module-info.class]
完美解决tomcat启动异常:Invalid byte tag in constant pool: 19;Unable to process Jar entry [module-info.class]
1252 0

热门文章

最新文章