作为Java程序员,会经常碰到jar包冲突,特别是涉及到的外部依赖越多,冲突概率就会越大。由于我们的应用代码都是使用maven来管理的,所以依赖的解决相对比较容易。不过最近碰到的一个问题,确实经历了好多步才最终定位。
现象:应用启动过程中,spring容器启动失败,错误日志很明确,找不到CollectionUtils.isEmpty()方法,jar冲突的典型症状之一。
首先,确认了这个类是apache的commons-collections中的工具类(在eclipse中ctrl+shift+T或者command+shitf+T寻找CollectionUtils是来自哪个jar中,同时也可以看看是不是含有这个方法),那么执行maven命令分析依赖树mvn dependency:tree -e -Dincludes=*:commons-collections*,看看应用中如何依赖commons-collections,依赖路径以及依赖版本。结果稍微出乎意料,有两个commons-collections依赖,只是groupId不同(这个时候maven是无能为力的,maven会认为这两个依赖是不同的,不会认为是一样的,因为maven对依赖的标识就是坐标,与jar中的内容无关),一个是apache-collections,另外一个是commons-collections,查看第二个中的CollectionUtils是有isEmpty方法的,第一个是没有的,而且第一个jar和第二个jar的包结构是完全相同的,apache-collections是外部系统的类库引入的,感觉好奇葩,于是果断排除之。重新查看依赖树,OK,打包重启,依然相同的错误。
接下来,打开war包,看下WEB-INF/lib下的commons-collections确实是3.2.1,没有问题。说明war包没有问题,最起码war内不会冲突,war包没问题。那就是jboss有问题,由于之前碰到过类似的问题,直接去${jboss_home}/server/default/lib下查看,升级其中的commons-collections到3.2.1即可(应用的jar和容器中的冲突的话,以容器为主,因为容器被优先加载),无需打包,重启jboss。自信满满地以为问题解决了,结果错误还是没变。
继续,查看jboss其他的目录,看不到commons-collections的影子。貌似到此,无路可走了。所以想想,服务器上肯定还有commons-collections-3.1存在,或许是在隐藏目录中(为毛当时没想起来用find名称搜索commons-collections)。没办法,只能通过打日志来看看CollectionUtils是从哪儿加载的了,使用了几行代码:
URL url = getClass().getClassLoader().getResource("org/apache/commons/collections/CollectionUtils.class"); LOG.error("CollectionUtils is loading from {}", url.getPath());
重新打包部署之后,查看日志信息,显示CollectionUtils是用WEB-INF/lib/commons-collections-3.2.1.jar中加载的,真的好意外,一直都在说,jboss中的jar优先加载啊,然后才会加载war的?那为神马会显示是用war中加载的呢?而且war中的是jar包版本是OK的,至此,基本无路可走了。除非?除非那个获取加载路径的代码是有问题的,因为和我的认知确实是冲突的。于是就getResource()方法去问了web容器方面的“神”,给出的解释是这个方法返回的路径不一定是真实的加载路径,和具体的容器实现有关。
最后,貌似打开了思路,但是什么办法可以知道类的真实记载路径呢?jvm启动参数跟踪,-XX:+TraceClassLoading加在jboss其中参数中,重启jboss,查看应用启动之后的jboss日志。好吧,日志文件很大,搜索下CollectionsUtils,确实是从一个隐藏目录加载的commons-collections,问题定位到了,解决办法不用说了。
如果前边真的用find命令搜索解决了问题,那么也不会有后边对认知的颠覆,那样还会一直认为那个api是救命稻草呢,不知道要持续到什么时候呢。另外,用find命令也只能去试探性地搜索commons-collections这个文件,但是不能排除有的类库会把commons-collections的代码内嵌在自己的jar中,这种事儿见到不少。所以走了最长的路,收获一定是最多的:)。
相关推荐
检查jar包冲突检查jar包冲突检查jar包冲突检查jar包冲突
在websphere8.5 下部署含有CXFwebservice的war包无法正常启动,...归根结底原因不是找不到类,而是发布后war下的jar与websphere自身平台下的jar冲突了,要解决此问题就要通过在websphere下建立共享库来根除,可参考附件
解决jar包冲突的工具类jarjar-1.4.rar,jar包冲突解决方法,解决jar与jar冲突,jar与aar冲突,不想删除任何一个包,只能修改其中一个jar包包名即可解决,解决方法详细请看这篇文章: ...
压缩包里面有myself工程。里面只有一个类。可以自己创建两个版本的myself的jar包,然后测试osgi解决jar包冲突。
easyExcel支持最低的POI版本是3.17,现有项目若已用POI版本比这高的话,希望不改变现有的引用,解决jar包冲突的话,使用该独立版的jar包。该包已改过包名,亲测可兼容使用,网上有说把poi升级到4.1.2但是试了导出...
该文档用于解决在websphere application server 服务部署程序过程中会出现jar包冲突问题
SSH整合jar包,彻底解决集成jar包冲突问题,内涵绝大部分常用框架的jar包和一些常用jar包
jar包冲突检测工具。使用方法,将需要检测的多个jar包放在同一路径下,打开工具一键检测生成冲突报告。
Maven的Jar包冲突问题,经常出现的场景为: 本地运行报NoSuchMethodError,ClassNotFoundException。明明在依赖里有这个Jar包啊。...定位冲突以及解决Jar包冲突的几个简单技巧 如何写一个干净依赖关系的POM文件
检测工具 jar包冲突
打开exe程序,选择项目jar包路径,就可以检测冲突的jar包了。
在tomcat下部署成功,迁移到weblogic下,报错,一般都是配置和jar包问题,配置问题开发根据报错能解决,jar冲突比较烦人,这里给出了解决方案。
因与cxf包xmlschema-core-*.jar 冲突 故重新打包 XmlSchema-1.1.jar 源码修改原类径的方法来重新打包避免冲突 源码放在javas.rar文件夹中 org.codehaus.xfire.wsdl11.parser.SchemaInfo org.codehaus.xfire....
项目启动后访问页面,页面显示Uncaught initialization Exception created by servlet这个错误.查看日志会报找不到index()的异常。
Hibernate+Struts jar包冲突问题
如何在WebSphere中解决jar包冲突.doc
ksoap2.jar和小米系统中的jar包冲突,修改ksoap的包名即可。
关于Myeclipse使用mybatis出现Jar包冲突的解决办法,这样操作之后不用每次部署都要删Jar包。(因为我们要使用Mybatis,所以使用Myeclipse里面自带的Mapper功能不全,是1.0.0版,所以我们要下最新一点的Mapper Jar包...