Reputation: 85
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?
Upvotes: 8
Views: 7998
Reputation: 838
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.
Upvotes: 0
Reputation: 5705
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.
Upvotes: 2
Reputation: 262514
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.
Upvotes: 5
Reputation: 26418
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.
Upvotes: 0
Reputation: 308041
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).
Upvotes: 8