如何解决jar包冲突包冲突问题

jar包冲突常见的异常为找不到类(java.lang.ClassNotFoundException)、找不到具体方法(java.lang.NoSuchMethodError)、字段错误(&java.lang.NoSuchFieldError)或者类错误(java.lang.LinkageError);
常见的解决方法如下:
1、首先做法是打出工程文件的依赖树,将根据jar包依赖情况判定是不是同一个jar包依赖了多个版本,如果确认问题所在,直接exclusion其中错误的jar包即可;
2、如果通过看依赖树不能确定具体冲突的jar包,可以使用添加jvm参数的方式启动程序,将类加载的具体jar信息打印出来;-verbose:class
3、经过上述步骤基本就可以解决jar包冲突问题,具体的问题要具体分析,当问题不可重现时上述方法均不会奏效;
如果当遇到应用重启冲突不可重现的情况建议将每次异常信息进行重点的保留,方便不可重现时进行分析;
例如,碰到一例bean初始化失败:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tfsManager' defined in URL [jar:file:/home/admin/wireless-qrshare/target/wireless-qrshare.war/WEB-INF/mon.config-1.0-SNAPSHOT.jar!/mobile/biz-service.xml]: Instanti nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [mon.tfs.DefaultTfsManager]: Constru nested exception is java.lang.VerifyError: Cannot inherit from final class
此时定位到tfsManager这个bean初始化内部调用的类:
通过查找定位到httpcore的版本存在冲突;
阅读(...) 评论()包冲突有关问题的解决办法 - 行业应用当前位置:& &&&包冲突有关问题的解决办法包冲突有关问题的解决办法&&网友分享于:&&浏览:268次包冲突问题的解决方法
包冲突是开发过程中很常见的问题:其表现有:1.明明在eclipse中能够索引到某个类,运行时却报出找不到类。2.明明在eclipse中能够索引到某个类的方法,运行时却报出找不到方法。3.类及方法都有,以正确编译成了.class文件,在本机跑的好好的,发到测试或者正式环境就抛如下异常:java.lang.NoClassDefFoundError: Could not initialize class
java.lang.VerifyError: ********* Incompatible argument to function这一类的话八成是包冲突。此时你在eclipse中用ctrl+shift+T 类名,一般可以看到会有不止一个的这个类,并且位于不同的jar中。这个时候就要考虑把那些干扰的冲突的包排除。如果使用maven,则直接如下排除即可。&dependency&
&groupId&com.XXX.udc&/groupId&
&artifactId&udc-client&/artifactId&
&version&1.0.4&/version&
&exclusions&
&exclusion&
&groupId&ch.qos.logback&/groupId&
&artifactId&logback-classic&/artifactId&
&/exclusion&
&/exclusions&
&/dependency&如果没用maven,可能要动手删除一些lib中的jar包了。日排错记录:测试环境好好的,预发环境一直报java.lang.NoClassDefFoundError,java.lang.VerifyError。步骤是:在eclipse里面通过ctrl+shift+T可以发现。import org.codehaus.jackson.JsonFimport org.codehaus.jackson.JsonGimport org.codehaus.jackson.map.ObjectM同时存在于两组jar中jackson-core-asl-1.8.8.jarjackson-mapper-asl-1.8.8.jar与jackson-core-lgpl-1.1.0.jarjackson-mapper-lgpl-1.4.0.jar第二组jar是我在pom中显示引用的,是我想要的。第一组jar是udc间接依赖的,于是我就把第一组的execution了。马上就好了。也就是说,一个工程中所依赖的包如果存在包名、类名的相同的类,在不同的环境下很可能引发加载的不一致问题,产生冲突,这是一个风险。还发现一个问题是,在我冲突解决之前,多次重启了预发环境机器,对于同一段代码,下面两个异常会随记出现,似乎在有潜在包冲突的情况下,即使相同的环境,不同的时刻jvm的加载执行历程都不同:java.lang.NoClassDefFoundError: Could not initialize class com.taobao.lifemarketweb.util.JackSonUtil与java.lang.VerifyError: (class: org/codehaus/jackson/map/ObjectMapper, method: writeValueAsBytes signature:& (Ljava/lang/O)[B) Incompatible argument to function&&&&&&& at com.taobao.lifemarketweb.util.JackSonUtil.&clinit&(JackSonUtil.java:20)排除如下:
&dependency&
&groupId&com.taobao.udc&/groupId&
&artifactId&udc-client&/artifactId&
&version&1.0.4&/version&
&exclusions&
&exclusion&
&groupId&ch.qos.logback&/groupId&
&artifactId&logback-classic&/artifactId&
&/exclusion&
&exclusion&
&groupId&org.codehaus.jackson&/groupId&
&artifactId&jackson-core-asl&/artifactId&
&/exclusion&
&exclusion&
&groupId&org.codehaus.jackson&/groupId&
&artifactId&jackson-mapper-asl&/artifactId&
&/exclusion&
&/exclusions&
&/dependency&
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有Maven怎么处理引用的jar版本冲突? - maven - ITeye群组
& 上一页 1
我找到的个项目 AAA的,但是用的是lucene3.0. 而我们现在的工程BBB里面已经用了lucene2.9-----我们的项目用这个AAA怎么处理lucene冲突啊?
&dependency&& &artifactId&aaa&/& &exclusions&&&& &exclusion&&&&&& &artifactId&lucene&/...
同一个artifactId,maven只会加载版本高的jar。不研究过,不十分确定这样的机制。
有同样的问题,当项目中依赖的两个包版本不一致的时候出现问题,我用的包是com.google.protobuffer,2.1和2.3冲突,用了一楼的做法,没有效果呀。
peizhyi 写道有同样的问题,当项目中依赖的两个包版本不一致的时候出现问题,我用的包是com.google.protobuffer,2.1和2.3冲突,用了一楼的做法,没有效果呀。
首先在 自己的 pom 中,人为不可能引入两个版本不同的依赖。冲突最可能的就是你依赖的依赖可能产生了冲突。
比如 A 依赖 版本为2.0 的 C ,B 依赖 版本为3.0的 C。在你的pom中,你同时依赖了 A 和 B ,这时就会产生冲突。这时候你就要判断,哪个版本能同时让A和B工作(如果可以的话),然后排除掉另一个就行了。我通常都是排除掉较低的版本。
&dependencies&
&dependency&
&groupId&A&/groupId&
&artifactId&A&/artifactId&
&version&xxx&/version&
&exclusions&
&exclusion&
&groupId&C&/groupId&
&artifactId&C&/artifactId&
&/exclusion&
&/exclusions&
&/dependency&
&dependency&
&groupId&B&/groupId&
&artifactId&B&/artifactId&
&/dependency&
&/dependencies&
bastengao 写道peizhyi 写道有同样的问题,当项目中依赖的两个包版本不一致的时候出现问题,我用的包是com.google.protobuffer,2.1和2.3冲突,用了一楼的做法,没有效果呀。
首先在 自己的 pom 中,人为不可能引入两个版本不同的依赖。冲突最可能的就是你依赖的依赖可能产生了冲突。
比如 A 依赖 版本为2.0 的 C ,B 依赖 版本为3.0的 C。在你的pom中,你同时依赖了 A 和 B ,这时就会产生冲突。这时候你就要判断,哪个版本能同时让A和B工作(如果可以的话),然后排除掉另一个就行了。我通常都是排除掉较低的版本。
&dependencies&
&dependency&
&groupId&A&/groupId&
&artifactId&A&/artifactId&
&version&xxx&/version&
&exclusions&
&exclusion&
&groupId&C&/groupId&
&artifactId&C&/artifactId&
&/exclusion&
&/exclusions&
&/dependency&
&dependency&
&groupId&B&/groupId&
&artifactId&B&/artifactId&
&/dependency&
&/dependencies&
比较让人郁闷的问题是,用了2.0的缺方法一,用了3.0的缺方法二。。这种问题还有解吗?
那这就是硬伤了
peizhyi 写道bastengao 写道peizhyi 写道有同样的问题,当项目中依赖的两个包版本不一致的时候出现问题,我用的包是com.google.protobuffer,2.1和2.3冲突,用了一楼的做法,没有效果呀。
首先在 自己的 pom 中,人为不可能引入两个版本不同的依赖。冲突最可能的就是你依赖的依赖可能产生了冲突。
比如 A 依赖 版本为2.0 的 C ,B 依赖 版本为3.0的 C。在你的pom中,你同时依赖了 A 和 B ,这时就会产生冲突。这时候你就要判断,哪个版本能同时让A和B工作(如果可以的话),然后排除掉另一个就行了。我通常都是排除掉较低的版本。
&dependencies&
&dependency&
&groupId&A&/groupId&
&artifactId&A&/artifactId&
&version&xxx&/version&
&exclusions&
&exclusion&
&groupId&C&/groupId&
&artifactId&C&/artifactId&
&/exclusion&
&/exclusions&
&/dependency&
&dependency&
&groupId&B&/groupId&
&artifactId&B&/artifactId&
&/dependency&
&/dependencies&
比较让人郁闷的问题是,用了2.0的缺方法一,用了3.0的缺方法二。。这种问题还有解吗?
同求啊。发生了同样的问题。 两个版本,高版本不兼容低版本的方法。目前的方案有两个 。一个是把其中的一个版本的maven坐标更换了,让两个都加载。不过还没有验证过。应该也会有问题。另外一个方法就是把低版本的包路径全部更换,再更换低版本的maven坐标,防止冲突。但是这些方法太繁琐,而且感觉不靠谱呀!有没有更好的方法解决?
cosmo1987 写道peizhyi 写道bastengao 写道peizhyi 写道有同样的问题,当项目中依赖的两个包版本不一致的时候出现问题,我用的包是com.google.protobuffer,2.1和2.3冲突,用了一楼的做法,没有效果呀。
首先在 自己的 pom 中,人为不可能引入两个版本不同的依赖。冲突最可能的就是你依赖的依赖可能产生了冲突。
比如 A 依赖 版本为2.0 的 C ,B 依赖 版本为3.0的 C。在你的pom中,你同时依赖了 A 和 B ,这时就会产生冲突。这时候你就要判断,哪个版本能同时让A和B工作(如果可以的话),然后排除掉另一个就行了。我通常都是排除掉较低的版本。
&dependencies&
&dependency&
&groupId&A&/groupId&
&artifactId&A&/artifactId&
&version&xxx&/version&
&exclusions&
&exclusion&
&groupId&C&/groupId&
&artifactId&C&/artifactId&
&/exclusion&
&/exclusions&
&/dependency&
&dependency&
&groupId&B&/groupId&
&artifactId&B&/artifactId&
&/dependency&
&/dependencies&
比较让人郁闷的问题是,用了2.0的缺方法一,用了3.0的缺方法二。。这种问题还有解吗?
同求啊。发生了同样的问题。 两个版本,高版本不兼容低版本的方法。目前的方案有两个 。一个是把其中的一个版本的maven坐标更换了,让两个都加载。不过还没有验证过。应该也会有问题。另外一个方法就是把低版本的包路径全部更换,再更换低版本的maven坐标,防止冲突。但是这些方法太繁琐,而且感觉不靠谱呀!有没有更好的方法解决?
现在想想看,有一个方法相对可行。把应用这两个版本不同方法的部分,拆成两个子项目,两个子项目各自引用不同版本的包。这样就能够同时引用,也不会冲突。
peizhyi 写道cosmo1987 写道peizhyi 写道bastengao 写道peizhyi 写道有同样的问题,当项目中依赖的两个包版本不一致的时候出现问题,我用的包是com.google.protobuffer,2.1和2.3冲突,用了一楼的做法,没有效果呀。
首先在 自己的 pom 中,人为不可能引入两个版本不同的依赖。冲突最可能的就是你依赖的依赖可能产生了冲突。
比如 A 依赖 版本为2.0 的 C ,B 依赖 版本为3.0的 C。在你的pom中,你同时依赖了 A 和 B ,这时就会产生冲突。这时候你就要判断,哪个版本能同时让A和B工作(如果可以的话),然后排除掉另一个就行了。我通常都是排除掉较低的版本。
&dependencies&
&dependency&
&groupId&A&/groupId&
&artifactId&A&/artifactId&
&version&xxx&/version&
&exclusions&
&exclusion&
&groupId&C&/groupId&
&artifactId&C&/artifactId&
&/exclusion&
&/exclusions&
&/dependency&
&dependency&
&groupId&B&/groupId&
&artifactId&B&/artifactId&
&/dependency&
&/dependencies&
比较让人郁闷的问题是,用了2.0的缺方法一,用了3.0的缺方法二。。这种问题还有解吗?
同求啊。发生了同样的问题。 两个版本,高版本不兼容低版本的方法。目前的方案有两个 。一个是把其中的一个版本的maven坐标更换了,让两个都加载。不过还没有验证过。应该也会有问题。另外一个方法就是把低版本的包路径全部更换,再更换低版本的maven坐标,防止冲突。但是这些方法太繁琐,而且感觉不靠谱呀!有没有更好的方法解决?
现在想想看,有一个方法相对可行。把应用这两个版本不同方法的部分,拆成两个子项目,两个子项目各自引用不同版本的包。这样就能够同时引用,也不会冲突。
拆成两个子项目,如果是指maven项目下的两个module的话,最后构建maven的web项目时两个module所依赖的jar会打包到一个war中。问题没有解决。而如果是指两个maven项目并且分别部署的话,这样仅仅为了隔离jar依赖而拆项目,这个项目也不好拆。毕竟拆项目的依据还是在当一个应用过大,需要降低耦合划分成两个子系统的时候才需要做。之前又想到两个解决方案。不过还有待权衡。1.引入OSGI架构。架构的引入可以很好的以组件的形式可插拔的更换模块,并且可以很好的做到jar隔离。但是OGSI的引入又会带来很多其他的麻烦。学习成本增加,OSGI的引入必然带来整个项目结构的变动,而且引入OSGI后,所有的模块都必须以OSGI的方式进行,对于一些觉得很简单且没有必要使用OSGI方式编写的代码,不能被OSGI引用。2.自己实现web container下一级的application classloader。对于一些特殊的jar使用配置的方式让自己实现的classloader进行加载。在classloader这一层做到隔离后的jar相互调用问题。这个classloader的实现确实是一个技术活。需要解决很多问题。开发成本提高很多。目前为止还是没有想出简单方便的方法解决这个问题。
& 上一页 1一、问题定义
最近在用sbt打assembly包时出现问题,在package的时候,发生jar包冲突/文件冲突问题,两个相同的class来自不同的jar包在classpath内引起冲突。
具体是:我有一个self4j的jar, 还有一个hadoop-common-hdfs的jar包,其中hadoop-common-hdfs.jar内包含了self4j这个jar包,导致冲突。
此类异常一般是由于打包不规范和打包疏忽引起的。
(个人认为正确的打包策略是:只打包自己核心功能,不将依赖打包在一起,但是有时为了方便不得不打在一起,所以要注意可能会出现上述问题)
异常log如下:
[trace] Stack trace suppressed: run last *:assembly for the full output.
[error] (*:assembly) deduplicate: different file contents found in the following:
[error] C:\Users\shengli.victor\.ivy2\cache\org.slf4j\slf4j-api\jars\slf4j-api-1.7.7.jar:org/slf4j/IMarkerFactory.class
[error] C:\Users\shengli.victor\.ivy2\cache\com.xxx.xx.hdfsfile\hdfscommon\jars\hdfscommon-1.1.jar:org/slf4j/IMarkerFactory.class
[error] Total time: 4 s, completed
异常很明显,来自2个不同的jar包self4j, &hdfscommon-1.1.jar里,在org/slf4j/IMarkerFactory.class这个类冲突了。
hdfscommon-1.1/jar
slf4j-api-1.7.2.jar
二、解决方案
解决jar包冲突有两种方案:
1、删除其中的某个jar,或者说,在打包的时候,不将2个相同的class打在同一个jar包内的classpath内,即exclude jar。
2、合并冲突
1.&Excluding JARs and files
%&&provided&
将相同的jar中排除一个,因为重复,可以使用&provided&关键字。
例如spark是一个容器类,编写spark应用程序我们需要spark core jar. 但是真正打包提交到集群上执行,则不需要将它打入jar包内。
这是我们使用 % &provided& 关键字来exclude它。
libraryDependencies ++= Seq(
&org.apache.spark& %% &spark-core& % &0.8.0-incubating& % &provided&,
&org.apache.hadoop& % &hadoop-client& % &2.0.0-cdh4.4.0& % &provided&
Maven defines&&as:
This is much like&compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scopeprovided&because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
2、Merge Strategy
如果在相对路径下,有多个相同的文件或者jar,这时我们可以使用Merge策略。
在build.sbt中对assemblyMergeStrategy&进行定义。
mergeStrategy in assembly &&= (mergeStrategy in assembly) { (old) =&
case PathList(&org&, &slf4j&, xs @ _*)
=& MergeStrategy.first
case PathList(ps @ _*) if ps.last endsWith &axiom.xml& =& MergeStrategy.filterDistinctLines
case PathList(ps @ _*) if ps.last endsWith &Log$Logger.class& =& MergeStrategy.first
case PathList(ps @ _*) if ps.last endsWith &ILoggerFactory.class& =& MergeStrategy.first
case x =& old(x)
解决方法:将org, slf4j 这个下的所有类和文件,都做合并, 采用的策略是:在classpath里,2选1,选的是classpath顺序里第一个self4j。
这里支持多种格式,例如ps.lat endsWith &axiom.xml& ,是以axiom.xml为结尾的文件,都采用filterDistinctLines策略,即合并两个文件,舍去重复的部分。
通过以上修改,终于解决了slf4j冲突的问题,即deduplicate: different file contents found in the following问题。
合并策略有很多种:
可以参考官方sbt assembly文档:
MergeStrategy.deduplicate&is the default described above
MergeStrategy.first&picks the first of the matching files in classpath order
MergeStrategy.last&picks the last one
MergeStrategy.singleOrError&bails out with an error message on conflict
MergeStrategy.concat&simply concatenates all matching files and includes the result
MergeStrategy.filterDistinctLines&also concatenates, but leaves out duplicates along the way
MergeStrategy.rename&renames the files originating from jar files
MergeStrategy.discard&simply discards matching files
更多的写法,example:
assemblyMergeStrategy in assembly := {
case PathList(&javax&, &servlet&, xs @ _*)
=& MergeStrategy.first
case PathList(ps @ _*) if ps.last endsWith &.html& =& MergeStrategy.first
case &application.conf&
=& MergeStrategy.concat
case &unwanted.txt&
=& MergeStrategy.discard
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)
& 碰到类似的问题不要慌张,仔细看log描述的是什么意思。
& 异常报出内容冗余的冲突,在看路径,发现在classpath内有完全相同的2个类,这是导致问题的根本原因。
& 找出原因,解决方发,消除冲突两种方法,一直是去除法,另一种是合并法。
& 相对于maven和gradle,sbt的冲突解决方法还是比较接近底层。如果没记错的话,maven和gradle都能自动解决冲突。

我要回帖

更多关于 jar包冲突怎么解决 的文章

 

随机推荐