减少外部 jar 文件大小

发布于 2024-08-28 09:48:39 字数 216 浏览 7 评论 0 原文

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

I've developed a module for a Java project. The module depends on external library (fastutil). The problem is, the fastutil.jar file is a couple of times heavier than the whole project itself (14 MB). I only use a tiny subset of the classes from the library. The module is now finished, and no-one is likely to extend it in future. Is there a way I could extract only the relevant class to some fastutil_small.jar so that others don't have to download all this extra weight?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

指尖凝香 2024-09-04 09:48:39

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

您可以仅使用该功能,并且已经获得了相当多的节省,

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

Obfuscation tools such as ProGuard usually provide a feature to remove unused classes (and even fields and methods) from the jar file. You have to be careful to verify everything still works, 'though, because you might be using reflecton to access classes or methods that ProGuard can't analyze.

You can use only that feature and already get quite some saving

Or you could combine it with other space-saving obfuscation techniques (such as class and method renaming) to save even more space at the cost of harder debugging (your stack traces will become harder to parse).

永不分离 2024-09-04 09:48:39

来自fastutil的安装说明

请注意,由于类数量较多,jar 文件很大:如果您打算发布自己的 jar 并包含一些 fastutil 类,则应该查看 AutoJar(也可以在 JPackage 上找到)自动提取必要的类。

From the installation instructions of fastutil:

Note that the jar file is huge, due to the large number of classes: if you plan to ship your own jar with some fastutil classes included, you should look at AutoJar (also available at JPackage) to extract automatically the necessary classes.

心是晴朗的。 2024-09-04 09:48:39

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

As fastutil is LGPL open-source software, you could just copy the relevant source files to your project and drop that jar file. The compiler will then tell you if have all the files you need. Just keep the packages as they are and put a copy of the fastutil license file on top.

甜妞爱困 2024-09-04 09:48:39

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

Yeah one crude is to have a backup of your original jar. then remove all unused class files from the jar. and there may be some internal references to other class which you can add as and when it is required. ie while executing it may throw a class not found exception so then you can add that class from the original jar to this jar.

Oo萌小芽oO 2024-09-04 09:48:39

对于任何复杂的项目,我个人都会避免使用 Proguard 来实现缩小 fastutil 等外部库的特定目的,因为这样做目前需要大量配置来指定所有将要修改的 jar 和那些要保持不变的 jar。您还必须指定过滤器,以将源内容从输入 jar 获取到正确的输出 jar 中。

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

我认为 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 更容易设置和排除故障。

For a project of any complexity, I would personally avoid Proguard for this very specific purpose of shrinking an external library like fastutil because doing so currently requires considerable configuration to specify all the jars that will be modified and those that are to be left intact. You will also have to specify the filters to get the source contents from your input jars into the correct output jars.

On top of that, the tool does not like to modify external jar files without having access to modify the application jar file. It will generate an error as a 'warning' even when only using the shrink option that indicates a library that is to be updated is referenced by a fixed jar file. If you are only shrinking the code and doing no optimizations or obfuscation, this requirement is an unnecessary limitation. In my case, this was forcing me to include a whole set of library references in my Proguard configuration as inputs when my only goal was to eliminate classes from the fastutil jar that I do not use.

I think Proguard could solve this issue with minor changes but for right now, I found its usage for the purpose to be frustrating and time consuming. Instead I offer up this solution for anyone who has this specific problem.

In this example, I use ant to clearly remove those primitive types that I do not use in my application and then remove the specific implementations of maps that I do not use. With this configuration, I reduced the jar file from 23Mb to 5Mb which was sufficient for my case.

<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>

While this is not the optimal solution, it is easier to setup and troubleshhoot than using Proguard.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文