sbt公布assembly解决jar包冲突 deduplicate: different file contents found in the following

转载 2016年12月11日 15:46:41

sbt assembly

    近期使用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



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

利用maven工具解决jar包冲突问题或重复加载问题

在使用maven开发项目的过程中,经常会遇到jar包重复加载或者jar包冲突的问题的,但是由于有些jar是由于maven的依赖加载自动加载进来的, 而不是开发者自己配置的,特别是当项目中pom中配置的...
  • w1014074794
  • w1014074794
  • 2016年07月12日 21:40
  • 15640

sbt发布assembly解决jar包冲突问题 deduplicate: different file contents found in the following

一、问题定义最近在用sbt打assembly包时出现问题,在package的时候,发生jar包冲突/文件冲突问题,两个相同的class来自不同的jar包在classpath内引起冲突。具体是:我有一个...
  • u014388509
  • u014388509
  • 2014年11月20日 20:48
  • 10668

sbt发布assembly解决jar包冲突问题 deduplicate: different file contents found in the following

一、问题定义     最近在用sbt打assembly包时出现问题,在package的时候,发生jar包冲突/文件冲突问题,两个相同的class来自不同的jar包在classpath内引起冲突。...
  • u013045749
  • u013045749
  • 2016年02月04日 16:52
  • 1083

sbt assembly遇到的两个问题

1.  deduplicate file appears in two different jar: If multiple files share the same relative path...
  • u012075079
  • u012075079
  • 2017年09月27日 09:40
  • 179

Spark sbt-assembly 打包

因为要用spark2.0,而集群上cdh5.7.1的spark版本是1.6的,在单独使用spark2.0的时候出现了hbase包找不到的问题,因为spark-submit –jars属性引的包太多,就...
  • github_36869152
  • github_36869152
  • 2017年01月16日 12:46
  • 1750

HIVE以及OOZIE添加第三方JAR包的方法

很多时候,我们需要在HIVE中引入第三方jar包或者是自己编写的“UDF”jar包。在HIVE中,涉及指定外部jar包的配置有两个地方: hive-site.xml中的配置项“hive.aux.jar...
  • bluishglc
  • bluishglc
  • 2015年05月26日 10:55
  • 11436

oozie使用中的一些小结

关于oozie 寻找包寻找位置原则:     oozie在运行的时候 只会去两个地方寻找自己需要的lib 1 回去当前提交任务的workflow所在的hdfs目录下的li...
  • jarth
  • jarth
  • 2016年10月12日 18:32
  • 1622

sbt-assembly 发布 Scala 项目

sbt-assembly 是一个非常实用的sbt插件,可以将当前项目的二进制包以及依赖的所有第三方库都打包成一个jar包发布,即one-jar, 对于那种直接运行的应用程序很方便。 sbt版本:0....
  • BeautyGao
  • BeautyGao
  • 2014年06月19日 08:19
  • 6939

OOZIE系统遇到的各种问题解决

这玩意儿装起来真是呕心沥血。 网上找不到编译后的文件,下载下来是源码,大小只有2.27 MB……编译完变成2GB了。 得装mysql 得装maven(这个尤其重要) 得配置hadoop代理等等 /e...
  • u010770993
  • u010770993
  • 2017年04月21日 10:54
  • 1611

Oozie4.2 安装部署、以及example测试

编译: 使用的环境是:Hadoop2.6.0、Spark1.4.0、Hive0.13.1、Sqoop1.4.4 编译Oozie的命令:./mkdistro.sh -Phadoop-2 -Dhadoop...
  • u014729236
  • u014729236
  • 2015年08月01日 19:51
  • 11999
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:sbt公布assembly解决jar包冲突 deduplicate: different file contents found in the following
举报原因:
原因补充:

(最多只允许输入30个字)