如何通过IDEA快速定位和排除依赖冲突问题

发布时间:2021-07-22 16:04:48 作者:小新
来源:亿速云 阅读:766

小编给大家分享一下如何通过IDEA快速定位和排除依赖冲突问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

前言

我们程序员在开发的时候经常会遇到各种各样的 BUG 问题,其中大部分是业务逻辑异常,还有一些是代码书写不规范造成的异常例如:NullPointException(NPE),IndexOutOfBoundsException 等等,其实这些我们都好定位和修复。但是还有一些运行时异常定位起来是特别头疼的,那就是 jar 包冲突引起的异常。

一般程序在运行时发生类似于 java.lang.ClassNotFoundException , Method not found: '......' ,或者莫名其妙的异常信息,这种情况一般很大可能就是 jar包依赖冲突的问题引起的了。

至于为什么会发生 jar包依赖冲突?这种问题大致可以归纳为如下几个原因:

可以看到,其实总的来说 jar 包冲突的主要原因就是依赖的版本冲突。

异常发生

项目中需要导出报表,技术选型的时候,一般是选用 Apache POI,但是 POI 的使用方式比较基础,开发量大,容易出现内存溢出的问题。

考虑到阿里开源了一套解析和生成Excel的工具 - EasyExcel,具有避免内存溢出OOM的情况发生,而且使用方便简单,所以就将它引入到了我们的项目中,具体的使用版本是 1.0.2。

<dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>easyexcel</artifactId>
 <version>1.0.2</version>
</dependency>

而另一个模块需要使用 POI 的将 Word 转成 PDF 的功能,所以同时又引入了如下 POI 的依赖:

<!-- poi utils -->
<dependency>
 <groupId>org.apache.poi</groupId>
 <artifactId>poi</artifactId>
 <version>3.15</version>
</dependency>
<dependency>
 <groupId>org.apache.poi</groupId>
 <artifactId>poi-ooxml</artifactId>
 <version>3.15</version>
</dependency>

我们从 Maven Repository 可以发现,阿里 EasyExcel 1.0.2 依赖的 POI 也是 3.15,所以照理说应该是没问题的。

如何通过IDEA快速定位和排除依赖冲突问题

但是在接口调试的时候还是出问题了,而且异常信息很奇怪,不是看一眼就能知道问题原因的并解决的。

Caused by: java.lang.AbstractMethodError: org.apache.xerces.dom.DocumentImpl.getXmlStandalone()Z
 at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.setDocumentInfo(DOM2TO.java:377)
 at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:131)
 at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:98)
 at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:693)
 at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:737)
 at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:351)
 at org.apache.poi.openxml4j.opc.StreamHelper.saveXmlInStream(StreamHelper.java:80)
 at org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller.marshallRelationshipPart(ZipPartMarshaller.java:181)
 at org.apache.poi.openxml4j.opc.ZipPackage.saveImpl(ZipPackage.java:560)
 at org.apache.poi.openxml4j.opc.OPCPackage.save(OPCPackage.java:1557)
 at org.apache.poi.POIXMLDocument.write(POIXMLDocument.java:248)
 at org.apache.poi.xssf.streaming.SXSSFWorkbook.write(SXSSFWorkbook.java:941)
 at com.alibaba.excel.write.ExcelBuilderImpl.finish(ExcelBuilderImpl.java:64)
 at com.alibaba.excel.ExcelWriter.finish(ExcelWriter.java:95)
 at com.pingan.haofang.creams.common.utils.ExcelUtil.writeExcel(ExcelUtil.java:71)
 ......
 ... 65 common frames omitted

提取关键信息,可以看到错误类型 java.lang.AbstractMethodError ,这个错误类型望名知义:抽象方法错误。这种类型的错误和我们上面说的 ClassNotFoundException 类似,很大可能就是 Jar包依赖冲突所导致的。

异常定位

那我们来定位下是哪个 jar 包冲突了,只需要将冲突的 jar 包排除掉,留下正确的就可以了。

我们可以看到错误类型是 java.lang.AbstractMethodError ,错误类型后面是具体的错误信息描述 :

org.apache.xerces.dom.DocumentImpl.getXmlStandalone()Z ,意思是在包 org.apache.xerces.dom 下的类 DocumentImpl 它的方法 getXmlStandalone() 调用出现了错误。

那么具体是谁在调用呢?我们在异常信息的紧密下一行可以看到如下这一行代码:

at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.setDocumentInfo(DOM2TO.java:377)

在包路径 com.sun.org.apache.xalan.internal.xsltc.trax 下, DOM2TO 类代码的的第377行,有个 setDocumentInfo 方法,我们鼠标左键点进去,在该行加个 Debug 断点。

如何通过IDEA快速定位和排除依赖冲突问题

我们发现这个 DOM2TO 类是 JDK1.8中 rt.jar 包里面的,具体类路径如下:

如何通过IDEA快速定位和排除依赖冲突问题

通过断点调试得知,这个 document 对象是 DocumentImpl 实例,

如何通过IDEA快速定位和排除依赖冲突问题

这个DocumentImpl 的真实路径也是 JDK1.8中 rt.jar 包里面的,它是 CoreDocumentImpl 的子类,CoreDocumentImpl 是接口Document 的实现类。

package com.sun.org.apache.xerces.internal.dom;
public class DocumentImpl
 extends CoreDocumentImpl
 implements DocumentTraversal, DocumentEvent, DocumentRange {
 ......
}
CoreDocumentImpl
package com.sun.org.apache.xerces.internal.dom;
public class CoreDocumentImpl
  extends ParentNode implements Document {
  ......
}

我们在 CoreDocumentImpl 类中第983行发现了 getXmlStandalone 方法。

如何通过IDEA快速定位和排除依赖冲突问题

这时报错原因赤条条的摆在我们面前了,显而易见,DOM2TO类中 setDocumentInfo 方法的参数 Document 是属于 JDK1.8 中 rt.jar 包下类路径 com.sun.org.apache.xerces.internal.dom 下的实现类 DocumentImpl。而我们报错的信息提示中是:

Caused by: java.lang.AbstractMethodError: org.apache.xerces.dom.DocumentImpl.getXmlStandalone()Z
这个 org.apache.xerces.dom.DocumentImpl 明显不属于我们 JDK1.8 的 rt.jar 包,而且也没有 getXmlStandalone 这个方法。

所以得知,我的项目中 jar 包依赖冲突了,我们只需要排除掉 org.apache.xerces.dom.DocumentImpl 所属的 jar 包就可以了。如何排除呢?

排除冲突

我们在 IDEA 中双击 Shift 键,输入 DocumentImpl,得到如下结果:

如何通过IDEA快速定位和排除依赖冲突问题

可以发现,这里有两个 CoreDocumentImpl,一个是我们的 JDK1.8的,一个是属于 xerce的,而且确实在依赖的 maven jar 包中发现了 xercesImpl-2.4.0.jar,这个 jar包就是需要排除的 jar包。

如何通过IDEA快速定位和排除依赖冲突问题

发现了冲突的 jar包,我全局搜索关键字 xerces,并没有发现哪一个 pom 中有依赖的代码,所以很可能是其他的 jar 包传递依赖进来的。

我们借助 IDEA 的 maven 工具,在 maven 栏右键项目模块,选择 show Dependencies 或 Ctrl + Shift + Alt + U ,这时候会展示当前模块的 jar 包依赖图,如下:

如何通过IDEA快速定位和排除依赖冲突问题

虽然这里展示了很多冲突的jar包,其中红线连接的就是冲突的jar 包,但是我们 Ctrl + F 查询 xerces 还是没有结果。

所以我们需要额外的方式来解决,这时我想到了 IDEA 有个插件 Maven Helper ,具体的插件下载可以参考前面的内容,下载好插件后,我们打开 pom.xml 文件,在pom.xml 文件的左下方有个 Dependency Analyzer ,我们点击之后显示如下:

如何通过IDEA快速定位和排除依赖冲突问题

我们输入 xerces,选择以树形展示所有依赖,得到如下的信息显示。

如何通过IDEA快速定位和排除依赖冲突问题

清晰明了,原来这个罪魁祸首是被 file-web-sdk 带进来的,我们右键选择 Jump To Source 或者 F4 定位到这个 jar 在 pom.xml 的依赖引入位置,如下图所示,我们通过 exclusion 标签排除 xercesImpl 的引入即可。

<dependency>
 <groupId>com.xx.xx.gov.fileservice</groupId>
 <artifactId>file-web-sdk</artifactId>
 <exclusions>
  <exclusion>
   <groupId>xerces</groupId>
   <artifactId>xercesImpl</artifactId>
  </exclusion>
 </exclusions>
</dependency>

再次启动项目,测试接口发现功能正常了,整个排查过程也就结束了,IDEA的功能还是很强大的。

以上是“如何通过IDEA快速定位和排除依赖冲突问题”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

推荐阅读:
  1. Maven依赖传递排除指定的依赖关系
  2. 快速解决vue.js 模板和jinja 模板冲突的问题

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

idea

上一篇:Java中怎么利用注解和反射简化编程

下一篇:如何通过java.util.TreeMap源码加强红黑树

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》