sbt-assembly:生成一个最小的 JAR 文件

sbt-assembly: Generate a minimal JAR file

我一直在使用 sbt-assembly 为我的 scala 项目生成独立的 JAR 文件。但是,我想减小我的 JAR 文件的大小(目前大约为 150MB,并且那里确实有改进的空间)。

我使用以下命令列出生成的 JAR 文件的内容:

jar tf <JAR file>

这表明生成的 JAR 文件中有很多 类 没有在项目中使用。我相信这些 类 会作为第三方 JAR 的一部分包含在内。

问题

(a) 是否有一个选项可用于指示 sbt-assembly 生成一个最小的 JAR 文件,该文件不包含我的项目中未使用的第三方 类?

(b) 我可以使用 AssemblyStrategy 手动指定需要排除的文件。这是一个合理的策略吗?我有点担心使用这种方法 JAR 文件可能会抛出意外的 ClassNotFound 异常。

提前致谢。

不容易说出你的项目中使用了什么,什么没有使用。如果您将一个依赖项包含到一个项目中,它可能会引入一些其他的依赖项。这些子依赖项可能还需要它们自己的依赖项等等。

默认情况下,如果您在项目中包含一些依赖项,您打算使用它。依赖项的作者通常做同样的事情。因此,通常您可以扔掉的东西不多,这是有原因的。在某些情况下情况并非如此:

  • 依赖项作者包括仅在某些设置中使用的附加依赖项,不适用于您的项目
  • 当您实际上只需要其中之一时,您正在使用超级依赖项 libraries/features。

也有反例:Scalatest 不提供 pegdown 来生成 html 测试报告,因为您通常不需要它。但如果您尝试使用 -h 标志生成 html.

则可能需要它

想象一下使用 Apache Tika 进行 pdf 解析的情况。它包装 PDFBox 来进行解析。在解析 MS 文档的情况下,您不需要 all other libraries 的膨胀。最好的办法是不要通过 sbt excludesbt-assembly 规则手动排除文件,因为存在 错误的风险 并得到 运行 时间 class 加载异常。相反,您需要直接使用正确的依赖项,例如 PDFBox。不幸的是,在许多情况下,这是一项 大量手动工作 来找出您需要的所有依赖项,因此这是您的选择:简单而丰富的 JAR,或者痛苦而精简。

有两种排除依赖的方法:

  1. 排除 exclude 的传递依赖。请参阅文档 here.
  2. 不要使用顶级依赖项并在需要时手动添加其子依赖项。
  3. 好的,还有一个不太有趣的选项:使用 provided 并确保将库复制到目标环境并位于 class 路径上。如果您有许多使用相同库的 jar,这有助于共享它们。

您可以使用此插件可视化您的依赖关系树:https://github.com/jrudolph/sbt-dependency-graph. It's very helpful when trying to figure out what you are using and what you can remove. There are some tools like tattletale and loosejar 人们建议但我还没有尝试过。如果有人对此有经验,请分享。

可能要看的是 treeshakers

对于 Java 有以下内容(我没有 tried/used):

http://proguard.sourceforge.net/