【问题标题】:Reduce external jar file size减小外部 jar 文件大小
【发布时间】:2010-04-09 09:52:11
【问题描述】:

我为 Java 项目开发了一个模块。该模块依赖于外部库 (fastutil)。问题是,fastutil.jar 文件比整个项目本身 (14 MB) 重几倍。我只使用库中的一小部分类。该模块现已完成,将来可能没有人扩展它。有没有办法我可以只将相关类提取到一些fastutil_small.jar,这样其他人就不必下载所有这些额外的重量?

【问题讨论】:

  • 好吧,将我的模块添加到项目中。这是几个相对较小的 java 包。我想要的是我对“fastutil”中的几个类的依赖不应该将项目的大小增加三倍。

标签: java jar size


【解决方案1】:

诸如ProGuard 之类的混淆工具通常提供一个功能,可以从 jar 文件中删除未使用的类(甚至字段和方法)。但是,您必须小心验证一切仍然有效,因为您可能正在使用反射来访问 ProGuard 无法分析的类或方法。

您只能使用该功能并且已经节省了很多

或者您可以将它与其他节省空间的混淆技术(例如类和方法重命名)结合使用,以节省更多空间,但代价是更难调试(您的堆栈跟踪将变得更难解析)。

【讨论】:

  • +1 前 5 个字正是我读到这个问题时的想法
  • 来自 proguard 指令:'ProGuard 需要指定输入 jar 的库 jar(或 war、ears、zip 或目录)。这些本质上是编译代码所需的库。 ProGuard 使用它们来重建正确处理所需的类依赖关系。库 jars 本身始终保持不变。您仍然应该将它们放在最终应用程序的类路径中。但是减小库 jar 文件的大小正是我想要的(还是我使用了错误的词汇?)。我错过了什么?
  • @joe:您可以通过-injars 而不是-libraryjars 指定库来轻松解决此问题
  • 最后我设法使用了autojar,但无论如何感谢您的帮助:)
  • 感谢您接受此答案,但如果您使用 autojar,您可能应该接受该答案 ;-)
【解决方案2】:

来自fastutil的installation instructions

请注意,由于类数量众多,jar 文件很大:如果您计划发布包含一些 fastutil 类的自己的 jar,您应该查看 AutoJar(也可在 JPackage 中获得)以自动提取必要的课程。

【讨论】:

  • 是的,我做了 rtfm :) 我只是还没能用它做任何有用的事情(菜鸟,还记得吗?:))
  • 好吧,事实证明,我所要做的就是尝试三遍。
【解决方案3】:

由于 fastutil 是 LGPL 开源软件,您只需将相关源文件复制到您的项目并删除该 jar 文件即可。然后编译器会告诉你是否有你需要的所有文件。只需保持包原样并将 fastutil 许可证文件的副本放在顶部即可。

【讨论】:

    【解决方案4】:

    是的,一个粗略的方法是备份您的原始 jar。然后从 jar 中删除所有未使用的类文件。并且可能有一些对其他类的内部引用,您可以在需要时添加它们。即在执行时可能会抛出一个找不到类的异常,因此您可以将该类从原始 jar 添加到此 jar。

    【讨论】:

      【解决方案5】:

      对于任何复杂的项目,我个人会避免使用 Proguard 来缩小像 fastutil 这样的外部库,因为这样做目前需要相当多的配置来指定所有将被修改的 jar 和那些将被留下的完好无损的。您还必须指定过滤器以将输入 jar 中的源内容获取到正确的输出 jar 中。

      最重要的是,该工具不喜欢修改外部 jar 文件而无法修改应用程序 jar 文件。即使仅使用收缩选项指示要更新的库被固定的 jar 文件引用,它也会生成错误作为“警告”。如果您只是缩小代码而不进行优化或混淆,则此要求是不必要的限制。就我而言,这迫使我在我的 Proguard 配置中包含一整套库引用作为输入,而我的唯一目标是从我不使用的 fastutil jar 中删除类。

      我认为 Proguard 可以通过微小的更改来解决这个问题,但现在,我发现它的用途令人沮丧且耗时。相反,我为遇到此特定问题的任何人提供此解决方案。

      在这个例子中,我使用 ant 清楚地删除了那些我在我的应用程序中不使用的原始类型,然后删除了我不使用的映射的特定实现。通过这种配置,我将 jar 文件从 23Mb 减少到 5Mb,这对于我的情况来说已经足够了。

      <jar destfile="F:/Programs/Java/JARS/fastutil-8.5.6-partial.jar">
          <zipfileset src="F:/Programs/Java/JARS/fastutil-8.5.6.jar">
              <!-- eliminate keys of specific primitive types -->
              <exclude name="it/unimi/dsi/fastutil/booleans/**"/>
              <exclude name="it/unimi/dsi/fastutil/chars/**"/>
              <exclude name="it/unimi/dsi/fastutil/doubles/**"/>
              <exclude name="it/unimi/dsi/fastutil/io/**"/>
              <exclude name="it/unimi/dsi/fastutil/longs/**"/>
              <!-- eliminate maps of specific implementations -->
              <exclude name="it/unimi/dsi/fastutil/**/*ArrayMap*"/>
              <exclude name="it/unimi/dsi/fastutil/**/*AVLTree*"/>
              <exclude name="it/unimi/dsi/fastutil/**/*CustomHash*"/>
              <exclude name="it/unimi/dsi/fastutil/**/*Linked*"/>
              <exclude name="it/unimi/dsi/fastutil/**/*RBTree*"/>
              <exclude name="it/unimi/dsi/fastutil/**/*Reference*"/>
          </zipfileset>
          <zipfileset src="F:/Programs/Java/JARS/fastutil-8.5.6.jar">
              <include name="**/*2ObjectFunction.class"/>
          </zipfileset>
      </jar>
      

      虽然这不是最佳解决方案,但它比使用 Proguard 更容易设置和排除故障。

      【讨论】:

        猜你喜欢
        • 2012-05-10
        • 1970-01-01
        • 2019-06-09
        • 1970-01-01
        • 2010-10-08
        • 2019-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多