一个、问题定义

近期使用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 2014-11-20 19:07:33

异常非常明显,来自2个不同的jar包self4j,  hdfscommon-1.1.jar里。在org/slf4j/IMarkerFactory.class这个类冲突了。

例如以下图:

hdfscommon-1.1/jar

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvb29wc29vbQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

slf4j-api-1.7.2.jar

二、解决方式

解决jar包冲突有两种方案:

1、删除当中的某个jar,或者说,在打包的时候。不将2个同样的class打在同一个jar包内的classpath内,即exclude jar。

2、合并冲突

1. Excluding JARs and files

% "provided"

将同样的jar中排除一个,由于反复。能够使用"provided"keyword。

比如spark是一个容器类,编写spark应用程序我们须要spark core jar. 可是真正打包提交到集群上运行,则不须要将它打入jar包内。

这是我们使用 % "provided" keyword来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 "provided" 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:

[warn] Merging 'META-INF\INDEX.LIST' with strategy 'discard'
[warn] Merging 'META-INF\MANIFEST.MF' with strategy 'discard'
[warn] Merging 'META-INF\maven\log4j\log4j\pom.properties' with strategy 'first'
[warn] Merging 'META-INF\maven\log4j\log4j\pom.xml' with strategy 'first'
[warn] Merging 'META-INF\maven\org.slf4j\slf4j-api\pom.properties' with strategy 'first'
[warn] Merging 'META-INF\maven\org.slf4j\slf4j-api\pom.xml' with strategy 'first'
[warn] Merging 'META-INF\maven\org.slf4j\slf4j-log4j12\pom.properties' with strategy 'first'
[warn] Merging 'META-INF\maven\org.slf4j\slf4j-log4j12\pom.xml' with strategy 'first'
[warn] Merging 'com\esotericsoftware\minlog\Log$Logger.class' with strategy 'first'
[warn] Merging 'com\esotericsoftware\minlog\Log.class' with strategy 'first'
[warn] Merging 'org\apache\log4j\helpers\LogLog.class' with strategy 'first'
[warn] Merging 'org\slf4j\ILoggerFactory.class' with strategy 'first'
[warn] Merging 'org\slf4j\IMarkerFactory.class' with strategy 'first'
[warn] Merging 'org\slf4j\Logger.class' with strategy 'first'
[warn] Merging 'org\slf4j\LoggerFactory.class' with strategy 'first'
[warn] Merging 'org\slf4j\MDC.class' with strategy 'first'
[warn] Merging 'org\slf4j\Marker.class' with strategy 'first'
[warn] Merging 'org\slf4j\MarkerFactory.class' with strategy 'first'
[warn] Merging 'org\slf4j\helpers\BasicMDCAdapter.class' with strategy 'first'
[warn] Merging 'org\slf4j\helpers\BasicMarker.class' with strategy 'first'
[warn] Merging 'org\slf4j\helpers\BasicMarkerFactory.class' with strategy 'first'
[warn] Merging 'org\slf4j\helpers\FormattingTuple.class' with strategy 'first'
[warn] Merging 'org\slf4j\helpers\MarkerIgnoringBase.class' with strategy 'first'
[warn] Merging 'org\slf4j\helpers\MessageFormatter.class' with strategy 'first'
[warn] Merging 'org\slf4j\helpers\NOPLogger.class' with strategy 'first'
[warn] Merging 'org\slf4j\helpers\NOPLoggerFactory.class' with strategy 'first'
[warn] Merging 'org\slf4j\helpers\NOPMDCAdapter.class' with strategy 'first'
[warn] Merging 'org\slf4j\helpers\NamedLoggerBase.class' with strategy 'first'
[warn] Merging 'org\slf4j\helpers\SubstituteLoggerFactory.class' with strategy 'first'
[warn] Merging 'org\slf4j\helpers\Util.class' with strategy 'first'
[warn] Merging 'org\slf4j\impl\Log4jLoggerAdapter.class' with strategy 'first'
[warn] Merging 'org\slf4j\impl\Log4jLoggerFactory.class' with strategy 'first'
[warn] Merging 'org\slf4j\impl\Log4jMDCAdapter.class' with strategy 'first'
[warn] Merging 'org\slf4j\impl\StaticLoggerBinder.class' with strategy 'first'
[warn] Merging 'org\slf4j\impl\StaticMDCBinder.class' with strategy 'first'
[warn] Merging 'org\slf4j\impl\StaticMarkerBinder.class' with strategy 'first'
[warn] Merging 'org\slf4j\spi\LocationAwareLogger.class' with strategy 'first'
[warn] Merging 'org\slf4j\spi\LoggerFactoryBinder.class' with strategy 'first'
[warn] Merging 'org\slf4j\spi\MDCAdapter.class' with strategy 'first'
[warn] Merging 'org\slf4j\spi\MarkerFactoryBinder.class' with strategy 'first'
[warn] Merging 'rootdoc.txt' with strategy 'concat'
[warn] Strategy 'concat' was applied to a file
[info] Strategy 'deduplicate' was applied to 373 files (Run the task at debug level to see details)
[warn] Strategy 'discard' was applied to 2 files
[warn] Strategy 'first' was applied to 38 files
[info] Done packaging.
[success] Total time: 84 s, completed 2014-11-20 19:04:52

合并策略有非常多种:

能够參考官方sbt assembly文档:https://github.com/sbt/sbt-assembly

http://stackoverflow.com/questions/19606243/resolving-dependencies-in-creating-jar-through-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
case x =>
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)
}

Final Qucik Hack:

假设以上写法都不奏效。还有最好一种,强制默认所有合并,不到万不得已,不要用。。
mergeStrategy in assembly <<= (mergeStrategy in assembly) { mergeStrategy => {
case entry => {
val strategy = mergeStrategy(entry)
if (strategy == MergeStrategy.deduplicate) MergeStrategy.first
else strategy
}
}}

三、总结

碰到相似的问题不要慌张。细致看log描写叙述的是什么意思。

异常报出内容冗余的冲突。在看路径,发如今classpath内有全然同样的2个类,这是导致问题的根本原因。

找出原因。解决方发。消除冲突两种方法。一直是去除法,另一种是合并法。

相对于maven和gradle。sbt的冲突解决方法还是比較接近底层。假设没记错的话,maven和gradle都能自己主动解决冲突。

本文仅针对该问题提出解决方式和思路。详细的各个配置还须要继续研究。

——EOF——

原创文章,转载请注明所:http://blog.csdn.net/oopsoom/article/details/41318599

sbt公布assembly解决jar包冲突 deduplicate: different file contents found in the following的更多相关文章

  1. Maven 解决JAR包冲突

    在JAR 冲突的情况下, 利用Eclipse方式解决JAR包冲突时比较方便简洁的,步骤如下 1. 在Eclipse 中打开pom.xml , 选择  “Dependency  Hierarchy” 2 ...

  2. idea升级maven工程jar包版本和解决jar包冲突

    原来用过eclipse的都知道,想要升级maven工程的jar包版本或者解决jar包冲突,直接在pom文件下的dependency hierarchy视图下右击冲突的jar包,将其exclude掉,然 ...

  3. 三十、详述使用 IntelliJ IDEA 解决 jar 包冲突的问题

    在实际的 Maven 项目开发中,由于项目引入的依赖过多,遇到 jar 冲突算是一个很常见的问题了.在本文中,我们就一起来看看,如何使用 IntelliJ IDEA 解决 jar 包冲突的问题!简单粗 ...

  4. mvn解决jar包冲突

    转自:http://blog.csdn.net/guanglihuan/article/details/50512855 对于Jar包冲突问题,我们开发人员经常都会有碰到,当我们使用一些jar包中的类 ...

  5. maven 解决jar包冲突及简单使用

    maven 解决jar包冲突 1.jar包冲突原因 maven中使用坐标导入jar包时会把与之相关的依赖jar包导入(导入spring-context的jar时就会把spring的整个主体导入) ,而 ...

  6. 【原】Maven解决Jar包冲突

    一.起源 引入二方jar maven 包后出现 NoSuchMethodError org.apache.commons.lang3.StringUtils.isNoneEmpty . 第一感觉就是j ...

  7. NoSuchMethodError idea解决jar包冲突

    报NoSuchMethodError(使用spring boot框架idea)一般是jar包冲突 Exception in thread"main" java.lang.NoSuc ...

  8. Maven中解决jar包冲突的三种方式

    首先我们在idea中创建一个maven工程,我们只关注pom.xml以及External Libraries中导入的jar包 导入spring-beans.jar <dependency> ...

  9. weblogic11g(10.3.6)部署war包时,解决jar包冲突的超简方案

    亲测有效:weblogic11g(10.3.6) + jdk7,打包使用jdk7或jdk8,注意weblogic用的jdk和打包时jdk的兼容. 分别配置web项目下pom.xml和weblogic. ...

随机推荐

  1. python 3.4.0 简单的print &#39;hello world&#39;,出错--SyntaxError: invalid syntax

    问题描写叙述: win7下安装的python 3.4.0版本号, 在命令行里写入简单的输出语句: print 'hello world' 然后enter,结果返回结果为: SyntaxError: i ...

  2. UVA - 11324 The Largest Clique 强连通缩点+记忆化dp

    题目要求一个最大的弱联通图. 首先对于原图进行强连通缩点,得到新图,这个新图呈链状,类似树结构. 对新图进行记忆化dp,求一条权值最长的链,每一个点的权值就是当前强连通分量点的个数. /* Tarja ...

  3. 走进spring之springmvc

    走进spring之springmvc 在动手之前,我们需要了解下springnvc.这里先献上一张springmvc的流程图及讲解. Spring的MVC框架是一个基于DispatcherServle ...

  4. Windows平台Oracle使用USE_SHARED_SOCKET角色

    前两天在一个朋友QQ集团提出了一个问题.背景例如,下面的: 继续问后,有例如以下回复: 1.对方server连接无问题. 2.从client能够telnetserver的1521port. 3.tns ...

  5. HDU 4085 Steiner树

    主题链接:pid=4085">http://acm.hdu.edu.cn/showproblem.php? pid=4085 由于这题专门花一晚上学习斯坦纳树.找到比較好的学习资料,链 ...

  6. 设计模式 - 观察者模式(Observer Pattern) 详细解释

    观察者模式(Observer Pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...

  7. Tips & Tricks:Apache log4j简明教程(二)

    在上一讲Apache log4j简明教程(一)中介绍了log4j的基本概念,配置文件,以及将日志写入文件的方法,并给出了一个详细的示例.这一讲,我在继续谈一谈如何使用log4j将日志写入MySQL数据 ...

  8. oracle11g的dmp文件导入oracle10g当误差:头验证失败---解决

    原创作品,离 "深蓝的blog" 博客.欢迎转载,转载时请务必注明出处.否则追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlong/ ...

  9. RQNOJ PID3 / Jam的计数法

    题目描述 Jam是个喜欢标新立异的科学怪人.他不使用阿拉伯数字计数,而是使用小写英文字母计数,他觉得这样做,会使世界更加丰富多彩.在他的计数法中,每个数字的位数都是相同的(使用相同个数的字母),英文字 ...

  10. hibernate中使用sql语句进行表链接查询,对结果集的遍历方法

    今天做了一个在hibernate中使用sql语句进行表链接查询的功能,得到的属性是来自两个表中的字段.下面对结果集遍历的方法进行记录. sql语句不写了.部分代码如下: List<Course_ ...