【问题标题】:Java - How to reduce the size of third-party jars to reduce the size of your applicationJava - 如何减小第三方 jar 的大小以减小应用程序的大小
【发布时间】:2011-04-07 11:21:59
【问题描述】:

我正在开发一个 java web 应用程序,其中包括 一个小程序。那个小程序是 依赖两个jar文件:

  • JFreeChart(用于在客户端绘制图表)- 1.7 mb(大小 jar 文件)
  • MySqlJdbcConnector(用于存储在客户端捕获的数据,以 远程数据库)- .7 mb(大小为 jar 文件)

现在,问题是上面的大小 两个jar文件。我的总大小 小程序 jar (myApplet.jar)2.5 mb 其中 2.4 mb 是 因为上面的两个jar文件。

我没有使用所有的类 那些jar文件。具体来说,对于 jfreechart,我使用的类非常少 图书馆。

===============================问题========= ==============================

Q1. 为了创建 myApplet.jar 文件,我已经解压缩了两个 jar 文件(jfreechart 和 mySQLJdbcConnector),然后打包了解压缩的版本jar 文件与我的小程序代码的源代码来创建一个单一的 jar 文件(即 myApplet.jar)。 这是用您的小程序代码打包第三方 jar 文件的正确方法吗?有什么办法可以优化吗?

Q2. 我试图找到我在我的应用程序中使用的 jfreechart 库的类的依赖项,以便仅将这些依赖项打包到 myApplet.jar 中。为此,我使用DependencyAnalyzer 来查找所有类的依赖关系。但后来我发现手动这样做很困难,因为每个类(我在我的应用程序中使用的 jfreechart 类)都有很多依赖项,而且我使用了大约 15 个 jfreechart 类,所以对每个类都这样做会非常困难。那么对此有什么建议吗?

Q3。这种情况是开发人员经常遇到的还是我错过了一些东西,因此我必须这样做?

【问题讨论】:

标签: java jar dependencies


【解决方案1】:

我建议尝试ProGuard。您可以排除您不使用的部分 jar 文件。

【讨论】:

  • 你知道它在多大程度上减少了罐子的大小吗?我知道这完全取决于否。我正在使用的类和依赖的百分比。但它仍然会显着减小尺寸吗?
  • @Yatendra:老实说,我前段时间用过一次,只是为了一个小型的 Hello World 类型的项目,所以我无法评论现实生活中的场景。由于 Google 使用适用于 Android 的 Proguard,优化和缩小对生命至关重要,因此我相信减小尺寸会很重要。
  • 非常感谢@darioo,这正是我想要的。
  • 如果您准备好在接下来的十年中与它抗争,请使用 proguard。不过你不会赢。
【解决方案2】:

是的,您可以通过创建一个仅包含您的小程序所需的类的 JAR 来节省空间。 (我见过这叫做 uber-JAR。)

有多种工具可以做到这一点;例如ProGuard、Zelix ClassMaster、一个我忘记名字的 Maven 插件等等。

然而,至少在一般情况下,有几个问题:

  • 如果您的代码使用动态加载(例如通过调用 Class.forName(className)),这些工具通常无法检测到依赖关系。因此,为了避免在最终 JAR 中遗漏动态加载的类,您需要告诉工具您的应用程序可能以这种方式显式加载的所有类的名称。

  • 您需要查看第三方库的许可证。 IIRC,某些许可证要求您以允许人们替换不同版本的库的方式将库包含在分布式工件中。有人可能会争辩说,一个 uber-JAR 让这很难做到,因此可能会出现问题。

JFreeChart 是 LGPL,而 LGPL 是具有上述要求的许可证。然而 MySQL 是 GPL,它胜过 LGPL,这意味着你的小程序必须是 GPL 的……如果你分发它。


最后,如果您想最小化您的 applet JAR 的大小,您不应该在 JAR 中包含您的源代码。源代码应位于单独的 JAR(或 ZIP、TAR 或其他)文件中。

【讨论】:

  • @Yatendra - 如果您不是指“[the] applet 的实际源代码”,为什么要说“[the] applet 的源代码”?我回答了你提出的问题,而不是你脑海中的问题。
  • @Yatendra - 话虽如此,无论您是否在小程序 JAR 中包含源代码,我的回答的主要部分都是有效的。您确实需要调查许可问题。
  • 您的第一个问题有问题,请参阅此链接以获取更多信息。 proguard.sourceforge.net/#manual/introduction.html
  • @HusseinPourakbar - 你在说什么?什么“第一题”?什么问题?
  • @Stephen C - 我在说:如果您的代码使用动态加载(例如通过调用 Class.forName("...")),这些工具通常无法检测到依赖关系。因此,为了避免在最终 JAR 中遗漏动态加载的类,您需要告诉工具您的应用程序可能以这种方式显式加载的所有类的名称。如果您阅读 proguard 手册,它说 proguard 可以检测到 class.forName("...")。
【解决方案3】:

A1:

您可以创建一个 ant 脚本或使用 Eclipse 或任何其他 IDE 来自动打包您的小程序。不过你的方法也是对的

A2:

我不会手动做这些事情。寻找传递依赖是非常复杂的。也许 darioo 的回答是更好的方法。

A3:

这确实很常见。一些提示:

您始终可以在没有调试信息的情况下重新构建这些第三方库。这应该会稍微减小这些库的大小。

另一方面,也许您不应该从您的小程序直接连接到数据库。您可以创建一个 RMI 接口(或类似的接口)来将您的 SQL 和结果数据传输到实际执行您的 SQL 的应用程序服务器。如果您不在安全的 Intranet 中运行,这对您的小程序来说是一个重要的安全方面。

【讨论】:

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