创建没有依赖关系的紧凑 jar

Creating compact jar without dependencies

给定一个常规 java gradle 项目,我们有一些在 jar 清单中定义的入口 main 方法,以及一堆依赖项。

现在通常当我们创建一个发行版时,我们可能会使用应用程序插件并有一些像这样的结构作为输出

/bin  (some splatform specific scripts that point to our jar)
/lib  (our jar + all dependencies with their dependencies etc...)

问题是,即使我们只使用了几个 类 来自我们的直接依赖项,它们和所有传递依赖项最终都会在一个分布中。例如,从 100M 的分布中只有 1M 实际上是可能 运行 并且可能与我们的应用程序有任何关系的代码...

像 proguard 这样的工具可以通过各种优化压缩特定 jar 中的代码,但它不会关心代码是否未被使用。未使用我的意思是 main 方法是 jar 的入口点,并且根据 main 中的代码,它可能永远不会使用实际应用程序 jar 中的大部分代码以及库 jar 中的更多代码...

我们的目标是创建这个只有实际使用的代码的 1M jar,同时考虑到 jar 清单中的主要方法是什么...

我搜索了很多但找不到任何解决方案,proguard 非常接近,但我找不到任何方法让它只关心代码的特定流程而不是所有代码。

有什么工具可以做到这一点吗?

您对 ProGuard 功能的描述是错误的:

Tool like proguard can shrink code in a particular jar with various optimizations but it won't care if the code is unused. By unused i mean the main method is the entry point of the jar, and depending on the code in main it may never ever use majority of the code in the actual application jar and a lot more in library jars...

您描述为 unused code 的正是 ProGuard 在其 收缩 步骤中所做的。从种子开始(在您的情况下是 main 方法),它将查找任何正在使用的 class/method 并删除其他所有内容。

如果保留的 class 太多,很可能是由于某些 -keep 规则。您必须根据需要调整它们。例如,如果第三方库不使用反射,则不需要保留。

ProGuard 还可以在其 优化 步骤中删除 dead code:根据流分析永远不会执行的方法内的任何指令都将被删除。该技术在指令级运行,而收缩在 class 级运行。