生成仅包含使用的类的最小化 jar

Posted

技术标签:

【中文标题】生成仅包含使用的类的最小化 jar【英文标题】:Generate minimized jar with only used classes 【发布时间】:2012-03-20 01:50:48 【问题描述】:

我需要创建用于 android 的最小 jar 实用程序库。我正在使用 apache 公共库中的一些方法(例如IOUtilsStringUtils)。然而,每一次这样的使用都会让我导入整个库(commons-langcommons-io 等),这在 Tomcat 下是绝对可以接受的(war 无论如何都是 mamoot 大小的),但对于 Android 项目绝对不能接受。

所以,我的目标是将所有使用过的类从依赖项打包到一个 jar 中——但只有那些需要的类。我记得曾经接触过完成该任务的 maven 插件,不幸的是我不记得它的名字,也无法通过 Google 找到它。

请问,您知道 maven 插件可以最小化依赖关系,还是任何独立工具可以做到这一点?

【问题讨论】:

【参考方案1】:

你不记得的maven插件可能是Apache Maven Shade Plugin,有minimizeJar选项。正如 Andreas_D 所注意到的,这不包括加载了 Class.forName 的类,所以你需要 implicity say in configuration,你需要它们。这是我如何让 maven 在我的单个 jar 中包含 jdbc 驱动程序:

<filter>
  <artifact>net.sourceforge.jtds:jtds</artifact>
    <includes>
      <include>**</include>
    </includes>
</filter>

【讨论】:

【参考方案2】:

对不起,也许我没有清楚地理解问题。混淆器工具(即ProGuard)可以做到这一点,不是吗?它将几个 JAR 打包成一个并剥离未使用的类。如果您不需要混淆/优化(以防止不必要的副作用),则可以禁用它们,启用“收缩”阶段。

【讨论】:

我发现ProGuard已经集成到Android SKD中了,所以我一定会看看它是否符合我的要求。 据我所知,这样的包装会破坏已签名的库 JAR。这可能是严重的劣势。 如果你重新打包库(剥离不需要的东西),那么如果你想要签名的代码,你逻辑上需要自己签名生成的版本。该库不再相同,并且在任何情况下都不应应用相同的签名。【参考方案3】:

一般来说,不可能自动选择应用程序使用的所有类。想想我们可以用Class.forName(String name) 做什么,或者我们是否使用依赖注入容器并在外部配置文件中声明类型。

【讨论】:

我知道,但这只是在您使用反射时。 AFAIR 这个工具在没有反射的情况下工作,但不能确定我真的见过它还是只是一个梦;) 不仅在您使用反射时 - 您可以从 url 加载一个类,并且该类可能依赖于您的类路径中的类。也会崩溃。 即使以编译器看不到的方式加载某些代码,它仍然非常有用。那些想要创建最小 jar 的人可以将无法自动找到的类列入白名单。【参考方案4】:

我猜如果您使用 Eclipse 来 JAR 项目,它会在 JARing 时提供一些选项来执行此操作 :) 也许会有用。

您还可以在自定义库下收集您使用的库类,并将此用户创建的库包含在项目中。

【讨论】:

以上是关于生成仅包含使用的类的最小化 jar的主要内容,如果未能解决你的问题,请参考以下文章

学习笔记:最小生成树算法

学习笔记:普里姆算法

包含具有 CString 成员变量的类的集合仅存储首字母

执行 Maven 补丁发布

仅包含带有程序的最小 Qt 库

Maven - 生成 Jar 和 War