You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sbt Assembly重复文件合并问题求助:已尝试方案仍未解决

解决sbt Assembly合并冲突与依赖树显示问题

先别急,咱们一步步拆解你遇到的两个核心问题:依赖树插件无法显示传递依赖,以及即使配置了合并策略仍存在重复内容冲突。


一、先修复依赖树插件不生效的问题

依赖树是排查重复依赖的关键,先确保它能正常工作:

1. 确认插件配置正确

在你的project/plugins.sbt文件中添加对应版本的依赖树插件(注意和你的sbt版本匹配,Scala 2.11.8对应sbt 0.13.x,所以用这个版本):

addSbtPlugin("net.virtual-void" % "sbt-dependency-tree" % "0.10.0-RC1")
// 同时确保sbt-assembly插件也正确配置
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.10")

2. 正确使用依赖树命令

在终端运行以下命令,就能看到完整的依赖关系:

  • 查看全量依赖树:sbt clean dependencyTree
  • 定位某一个依赖的来源:sbt whatDependsOn <groupId> <artifactId>
    比如想查log4j-core的依赖链:sbt whatDependsOn org.apache.logging.log4j log4j-core

如果还是没输出,检查sbt版本是否和插件兼容——sbt 0.13.x对应插件版本0.10.0-RC1,sbt 1.x则需要用1.2.0及以上版本。


二、解决sbt Assembly重复内容冲突

你已经用了Log4j2MergeStrategy,但冲突仍存在,大概率是合并策略覆盖不全面,或者有未被处理的重复依赖。以下是针对性的优化方案:

1. 完善合并策略配置

在你的build.sbt中,把合并策略调整得更全面,既要覆盖log4j2的特殊文件,也要处理其他常见冲突场景:

import sbtassembly.Log4j2MergeStrategy

name := "your-project-name"
organization := "your-org"
version := "0.1"
scalaVersion := "2.11.8"

val sparkVersion = "2.1.1"

resolvers ++= Seq(
  "Maven Central" at "https://repo1.maven.org/maven2/",
  "Spark Packages" at "https://dl.bintray.com/spark-packages/maven/"
)

libraryDependencies ++= Seq(
  "org.apache.spark" %% "spark-core" % sparkVersion % Provided,
  "org.apache.spark" %% "spark-sql" % sparkVersion % Provided,
  // 你的其他业务依赖
)

// 核心合并策略配置
assemblyMergeStrategy in assembly := {
  // 合并META-INF/services下的文件(去重行)
  case PathList("META-INF", "services", xs @ _*) => MergeStrategy.filterDistinctLines
  // 丢弃MANIFEST.MF,避免打包时冲突
  case PathList("META-INF", "MANIFEST.MF") => MergeStrategy.discard
  // 保留第一个LICENSE文件,避免重复
  case PathList("META-INF", "LICENSE") => MergeStrategy.first
  // 专门处理log4j2的配置文件和插件
  case x if Log4j2MergeStrategy.isLog4j2File(x) => Log4j2MergeStrategy.log4j2MergeStrategy(x)
  // 处理重复的class文件,优先保留第一个(如果是版本冲突,后续用dependencyOverrides统一)
  case x if x.endsWith(".class") => MergeStrategy.first
  // 其他文件沿用默认策略
  case x =>
    val defaultStrategy = (assemblyMergeStrategy in assembly).value
    defaultStrategy(x)
}

// 强制统一依赖版本,从根源避免传递依赖冲突
dependencyOverrides ++= Seq(
  "com.google.guava" % "guava" % "14.0.1", // Spark 2.1.1依赖的guava版本
  "org.apache.commons" % "commons-lang3" % "3.5"
)

2. 精准排查重复冲突

从assembly的报错信息里找到具体的重复文件(比如duplicate entry: org/apache/logging/log4j/core/lookup/JndiLookup.class),然后用依赖树命令找到这些文件来自哪些依赖:

  • 如果是同一库的不同版本,用dependencyOverrides强制统一版本
  • 如果是不同库的同名文件,要么排除其中一个依赖(用exclude),要么给该文件单独设置合并策略

三、额外注意事项

  • Spark依赖建议加% Provided,避免打包时把Spark自带的库也打进去,减少冲突概率
  • 如果使用了其他日志框架(比如logback),记得排除和log4j2冲突的依赖,比如在Spark依赖里加exclude("org.slf4j", "slf4j-log4j12")

内容的提问来源于stack exchange,提问作者donald

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:19:08