Reducing WebSocket client jar size with ProGuard

We already know there is a demand for standalone web socket client runnable even on different platforms than just Java EE or Java SE – Tyrus publishes client runtime all-in-one bundles for Java 6 (works on Android!) and Java 7+ (takes advantage of NIO API introduced in Java 7). In following article, we will try to create optimised version of these bundles to see whether they do contain some redundant classes. (spoiler: they do).

Tool of the choice for todays exercise would be ProGuard. Maybe not that easy to use, but it is low-level tool capable of various optimisations. We won’t cover any obfuscation, our goal is to create smaller jar with the same functionality.

Starting point is:

551K tyrus-standalone-client-jdk-1.10-SNAPSHOT.jar
1.9M tyrus-standalone-client-1.10-SNAPSHOT.jar

These jar files are representing two distribution which were already mentioned – client-jdk is Java 7 based client, client jar is Grizzly based (JDK 6+). For those who don’t know, Grizzly is Java NIO container, so it basically does the same thing as Java 7 NIO API, but in a little different manner. Also, Grizzly is the NIO framework of choice for Glassfish, Java EE reference implementation.

Downloading and executing ProGuard is not complicated, there is even GUI if you are more used to this kind of applications. After initial study and few trial runs, it seems I can produce optimised jar files with following configuration:

-dontoptimize
-dontobfuscate
-keepparameternames
-keepattributes Signature,InnerClasses,*Annotation*
-keepclassmembers,allowoptimization enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

-keep public class org.glassfish.tyrus.** { public protected private *; }

-keep public class javax.websocket.** { public protected *; }

-dontwarn

 The command line for running this configuration against Tyrus client distributions would look somehow like following:

proguard.sh -injars ./client-jdk/target/tyrus-standalone-client-jdk-1.10-SNAPSHOT.jar -outjars tyrus-client-jdk.jar -libraryjars $JAVA_HOME/jre/lib/rt.jar @tyrus-client.pro

(previous line is for client-idk distribution, but it is very similar to the other one; just for the completeness of presented data, I’m using JDK 8; if you are using different version, your “-libraryjars” parameter might need to be adjusted).

Result:

533K tyrus-client-jdk.jar
1.2M tyrus-client.jar

For the Java 7+ client distribution, the difference is actually quite small, so we can make an assumption that the distribution is already quite optimal. The other is different story – but there is a good reason for it. Java 6+ distribution is based on Grizzly and Grizzly is mainly written as a server, not as a client. We are reusing some stuff from there, but the problem seem to be in not optimal modularization for client usecases. Anyway, just to sum that up, ProGuard was able to find and remove approximately 700 kB of “not used code”.

The conclusion is that you should consider using tool similar to ProGuard, especially when you are redistributing any java application. Special note for Android developers: you are already doing this, maybe even without knowing – DexGuard seem to be standard part of Android application development lifecycle.

This entry was posted in java and tagged , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>