博客
关于我
sbt公布assembly解决jar包冲突 deduplicate: different file contents found in the following
阅读量:798 次
发布时间:2023-03-31

本文共 2611 字,大约阅读时间需要 8 分钟。

sbt 打包过程中 jar 包冲突的解决方案

在 sbt 打包过程中,类路径冲突是一个常见问题。这种冲突通常是由于同一类路径下有多个相同的 jar 包引入了相同的类导致的。以下是针对此问题的一些实用解决方案。


jar 包冲突的表现

类路径冲突的常见现象是当 sbt 尝试将多个 jar 包打包到同一个项目中时,某些类可能在两个或多个 jar 包中出现。这种情况通常发生在依赖包打包不规范时。例如,在项目中引入了 self4j 和 hadoop-common-hdfs 的 jar 包时,如果 hadoop-common-hdfs.jar 中包含了 self4j 的相关类,可能会导致类路径冲突。


常见问题示例

以下是 sbt 打包过程中可能遇到的 jar 包冲突日志示例:

[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

在上述日志中可以看到,org/slf4j/IMarkerFactory.class 这个类在两个不同的 jar 包中出现,导致了类路径冲突。


jar 包冲突的解决方法

1. 排除冲突的 jar 包

为了解决 jar 包冲突,可以选择排除其中一个 jar 包。具体操作方法如下:

  • build.sbt 文件中,使用 provided 关键字指定仅需要的 jar 包。
  • 例如:
libraryDependencies ++= Seq(  "org.apache.spark" %% "spark-core" % "0.8.0-incubating" % "provided",  "org.apache.hadoop" % "hadoop-client" % "2.0.0-cdh4.4.0" % "provided")

这样,Spark 和 Hadoop 的核心 jar 包不会被打包到最终的 jar 文件中,而是由运行环境(如集群)提供。

2. 使用合并策略

如果需要将冲突的 jar 包打包在一起,可以通过定义合并策略来解决类路径冲突。sbt 提供了多种合并策略,可以根据具体需求选择:

合并策略示例

build.sbt 中定义合并策略:

assemblyMergeStrategy in assembly := {  case PathList("org", "slf4j", xs @ _*) => MergeStrategy.first // 优先选择类路径顺序中的第一个 jar 包  case PathList(ps @ _*) if ps.last endsWith "axiom.xml" => MergeStrategy.filterDistinctLines // 对 axiom.xml 文件采用去重策略  case PathList(ps @ _*) if ps.last endsWith "Log$Logger.class" => MergeStrategy.first // 优先选择类路径顺序中的第一个 Log$Logger.class  case PathList(ps @ _*) if ps.last endsWith "ILoggerFactory.class" => MergeStrategy.first // 优先选择类路径顺序中的第一个 ILoggerFactory.class  case x => old(x) // 其他文件采用默认策略}

通过定义合并策略,可以控制类路径冲突的解决方式。例如,可以选择 MergeStrategy.first,即在类路径中第一个出现的类文件优先生效。


常见合并策略

sbt 提供了多种合并策略,可以根据具体需求选择:

  • MergeStrategy.deduplicate:默认策略,用于去除重复文件。
  • MergeStrategy.first:优先选择类路径顺序中的第一个 jar 包。
  • MergeStrategy.last:优先选择类路径顺序中的最后一个 jar 包。
  • MergeStrategy.singleOrError:如果检测到冲突,会报错并停止打包。
  • MergeStrategy.concat:将所有冲突的文件按顺序拼接。
  • MergeStrategy.filterDistinctLines:对于特定文件(如 axiom.xml),只保留唯一的内容。
  • MergeStrategy.discard:忽略冲突的文件。
  • MergeStrategy.rename:对 jar 文件进行重命名。

最终快速解决方法

如果以上方法仍然无法解决问题,可以尝试强制指定合并策略。例如:

assemblyMergeStrategy in assembly := {  mergeStrategy in assembly := {    case entry => {      val strategy = mergeStrategy(entry)      if strategy == MergeStrategy.deduplicate then MergeStrategy.first      else strategy    }  }}

这种方法可以强制将 deduplicate 策略改为 MergeStrategy.first,以解决类路径冲突。


总结

类路径冲突是 sbt 打包过程中常见的问题,通常由多个 jar 包引入了相同的类导致。解决方法包括排除冲突的 jar 包或通过定义合并策略来解决冲突。通过合理配置 build.sbt 文件,可以有效避免类路径冲突,并确保打包过程顺利进行。

转载地址:http://gsefk.baihongyu.com/

你可能感兴趣的文章
oracle00205报错,Oracle控制文件损坏报错场景
查看>>
Oracle10g EM乱码之快速解决
查看>>
Oracle10g下载地址--多平台下的32位和64位
查看>>
Oracle10g安装了11g的ODAC后,PL/SQL连接提示TNS:无法解析指定的连接标识符
查看>>
oracle11g dataguard物理备库搭建(关闭主库cp数据文件到备库)
查看>>
Oracle11G基本操作
查看>>
Oracle11g服务详细介绍及哪些服务是必须开启的?
查看>>
Oracle11g静默安装dbca,netca报错处理--直接跟换操作系统
查看>>
oracle12安装软件后安装数据库,然后需要自己配置监听
查看>>
Oracle——08PL/SQL简介,基本程序结构和语句
查看>>
Oracle——distinct的用法
查看>>
Oracle、MySQL、SQL Server架构大对比
查看>>
oracle下的OVER(PARTITION BY)函数介绍
查看>>
Oracle中DATE数据相减问题
查看>>
Oracle中merge into的使用
查看>>
oracle中sql查询上月、本月、上周、本周、昨天、今天的数据!
查看>>
oracle中sql的case语句运用--根据不同条件去排序!
查看>>
Oracle中Transate函数的使用
查看>>
oracle中关于日期问题的汇总!
查看>>
Oracle中常用的语句
查看>>