为什么 shadowJar minimise() 没有删除所有未使用的依赖项?
Why shadowJar minimise() is not removing all unused dependencies?
我正在尝试从一个项目生成两个不同的 jar,该项目是一个 monorepo,它包括对这个世界上许多伟大事物的依赖,所以不用说我不希望这些可执行 jar 有大尺寸并且会而是让它们只包含他们实际使用的 classes。
我按照此处的说明进行操作 https://imperceptiblethoughts.com/shadow/configuration/minimizing/
。
为了测试 shadowJar
任务是否真的有效,我创建了一个简单的 Main java 文件,它实际上只使用 java SDK。
public class Main {
public static void main(String[] args) {
System.out.println("client");
}
}
并添加了实际的 shadow jar 任务并将其指向主任务 class
shadowJar {
archiveBaseName.set('client')
archiveClassifier.set('')
archiveVersion.set('0.1')
minimize()
manifest {
attributes 'Main-Class': 'my.package.Main'
}
}
它正确生成了 uber jar(我能够 运行 它只是用 java -jar ...
),但是文件的大小是 10Mb。
然后我生成了一个没有 minimize()
部分的新版本,它是 15Mb。
我这里有什么地方做错了吗?
也许我对这个工具期望太高,而混淆器(尽管设置起来很乏味)是唯一的方法?
由于您没有向我们提供您的构建文件,我只能提供一些一般性建议:
- 确保这个
Main
class 是源代码树中唯一的文件(shadow 不关心 main class 是什么)
- 确保您的依赖项未标记为
api
正如您自己所说,最小化 有效 。我自己也用 many 依赖项做了一些测试(见下文)。 jar 文件在没有最小化的情况下为 187MB,并且有很多条目我需要启用 zip64。 Shadow 将其最小化为 25MB。
现在,那 25MB 从何而来?根据我在测试中看到的情况,有两种类型的文件会保留:
- 一般资源文件(实际上
META-INF
文件夹在我的测试用例中是 24MB)
package-info.class
和 module-info.class
(尽管尺寸可能小得多)
无法自动剥离,因为不清楚它们是否被使用。
如果您 100% 确定不需要其中一些文件,您可以 filter 手动将它们从 jar 中取出。虽然我怀疑这样做是否值得。
如果您认为还包含其他文件,您可以提取 Jar(jar 只是一个具有不同扩展名的 zip)并查看其内容。
测试用例
首先,我克隆了 Spring Boot,然后删除了所有不必要的模块(即除 spring-boot-project:spring-boot
、spring-boot-project:spring-boot-dependencies
和 spring-boot-project:spring-boot-parent
之外的所有模块)并更改了所有依赖项spring-boot-project:spring-boot
为 implementation
类型。
然后我删除了当前的源代码并用你的示例替换它 Main
class。
添加 shadow
插件后,我得到了一个大小为 187MB 的 jar。当我然后应用 minimize
它只有 25MB。
然后我提取了 Jar 和 运行 一些命令来删除每个 package-info
、module-info
和一般资源文件:
$> find \( \( -not -name "*.class" -or -name "package-info.class" -or -name "module-info.class" \) -and -not -type d \) -delete
$> find -empty -delete
我不知道 Windows 上是否有等效的命令。无论如何,执行上述操作后只剩下少数 class 个文件(144kB!),所以我认为可以说 shadow 正在完成它的工作。
我正在尝试从一个项目生成两个不同的 jar,该项目是一个 monorepo,它包括对这个世界上许多伟大事物的依赖,所以不用说我不希望这些可执行 jar 有大尺寸并且会而是让它们只包含他们实际使用的 classes。
我按照此处的说明进行操作 https://imperceptiblethoughts.com/shadow/configuration/minimizing/
。
为了测试 shadowJar
任务是否真的有效,我创建了一个简单的 Main java 文件,它实际上只使用 java SDK。
public class Main {
public static void main(String[] args) {
System.out.println("client");
}
}
并添加了实际的 shadow jar 任务并将其指向主任务 class
shadowJar {
archiveBaseName.set('client')
archiveClassifier.set('')
archiveVersion.set('0.1')
minimize()
manifest {
attributes 'Main-Class': 'my.package.Main'
}
}
它正确生成了 uber jar(我能够 运行 它只是用 java -jar ...
),但是文件的大小是 10Mb。
然后我生成了一个没有 minimize()
部分的新版本,它是 15Mb。
我这里有什么地方做错了吗? 也许我对这个工具期望太高,而混淆器(尽管设置起来很乏味)是唯一的方法?
由于您没有向我们提供您的构建文件,我只能提供一些一般性建议:
- 确保这个
Main
class 是源代码树中唯一的文件(shadow 不关心 main class 是什么) - 确保您的依赖项未标记为
api
正如您自己所说,最小化 有效 。我自己也用 many 依赖项做了一些测试(见下文)。 jar 文件在没有最小化的情况下为 187MB,并且有很多条目我需要启用 zip64。 Shadow 将其最小化为 25MB。
现在,那 25MB 从何而来?根据我在测试中看到的情况,有两种类型的文件会保留:
- 一般资源文件(实际上
META-INF
文件夹在我的测试用例中是 24MB) package-info.class
和module-info.class
(尽管尺寸可能小得多)
无法自动剥离,因为不清楚它们是否被使用。
如果您 100% 确定不需要其中一些文件,您可以 filter 手动将它们从 jar 中取出。虽然我怀疑这样做是否值得。
如果您认为还包含其他文件,您可以提取 Jar(jar 只是一个具有不同扩展名的 zip)并查看其内容。
测试用例
首先,我克隆了 Spring Boot,然后删除了所有不必要的模块(即除 spring-boot-project:spring-boot
、spring-boot-project:spring-boot-dependencies
和 spring-boot-project:spring-boot-parent
之外的所有模块)并更改了所有依赖项spring-boot-project:spring-boot
为 implementation
类型。
然后我删除了当前的源代码并用你的示例替换它 Main
class。
添加 shadow
插件后,我得到了一个大小为 187MB 的 jar。当我然后应用 minimize
它只有 25MB。
然后我提取了 Jar 和 运行 一些命令来删除每个 package-info
、module-info
和一般资源文件:
$> find \( \( -not -name "*.class" -or -name "package-info.class" -or -name "module-info.class" \) -and -not -type d \) -delete
$> find -empty -delete
我不知道 Windows 上是否有等效的命令。无论如何,执行上述操作后只剩下少数 class 个文件(144kB!),所以我认为可以说 shadow 正在完成它的工作。