我为 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?
发布评论
评论(5)
诸如 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).
来自fastutil的安装说明:
From the installation instructions of fastutil:
由于 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.
是的,一个粗略的做法是备份原始罐子。然后从 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.
对于任何复杂的项目,我个人都会避免使用 Proguard 来实现缩小 fastutil 等外部库的特定目的,因为这样做目前需要大量配置来指定所有将要修改的 jar 和那些要保持不变的 jar。您还必须指定过滤器,以将源内容从输入 jar 获取到正确的输出 jar 中。
最重要的是,该工具不喜欢在没有修改应用程序 jar 文件的权限的情况下修改外部 jar 文件。即使仅使用收缩选项,它也会生成一个错误作为“警告”,表明要更新的库被固定的 jar 文件引用。如果您只是缩小代码而不进行优化或混淆,那么此要求是不必要的限制。就我而言,当我唯一的目标是从 fastutil jar 中消除我不使用的类时,这迫使我在 Proguard 配置中包含一整套库引用作为输入。
我认为 Proguard 可以通过微小的改变来解决这个问题,但就目前而言,我发现它的使用是令人沮丧和耗时的。相反,我为遇到此特定问题的任何人提供此解决方案。
在此示例中,我使用 ant 明确删除我的应用程序中不使用的那些原始类型,然后删除我不使用的映射的特定实现。通过此配置,我将 jar 文件从 23Mb 减少到 5Mb,这对于我的情况来说已经足够了。
虽然这不是最佳解决方案,但它比使用 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.
While this is not the optimal solution, it is easier to setup and troubleshhoot than using Proguard.