I’ve been working on an improved version of Galactic Conquest 4K for this year’s Java4K contest. The purpose of this contest is to make the best game possible in just 4KB. This 4KB limit does not apply to the source code or classfile, but to the compressed (and optionally gzipped) jar file that will be deployed as an applet.
Some of the tricks involved in this aim at reducing the size of the bytecode that the Java compiler generates, for example to avoid using methods, using as few external references as possible, and compiling using a lower version of Java.
However, success in this contest also depends (besides a lot of creativity of course) on the approach used to compress the compiled classfile, which may reduce the size of the resulting compressed and gzipped jar file to a fraction of the size that the original jar file was.
For example, after some experimentation using an Ant script to try out different approaches to compressing the Constellation Control 4K (successor to Galactic Conquest 4K) classfile, I managed to reduce the original 10KB classfile to under 4KB, which even leaves me some room to add some extra features:
Size of class file: 10070
Size of original jar: 5652
Size of jar after proguard: 4946
Size of jar.pack after pack200-pack: 6802
Size of jar.pack.gz after pack200: 4143
Size of jar.pack.7.gz after 7zip: 4008
Size of jar.pack.kzip.gz after kzip 3964
It was interesting to notice that the differences between the different compression tools I used were quite significant: using pack200 for gzipping resulted in a 4143B size, using 7zip in a 4008, and using kzip resulted in the smallest size: 3964B. However, I’ve heard rumors that the different compression approaches may get different results depending on how the original class file is structured, so it may be worth it to try out different approaches regularly. To this end I’ve made an Ant script that goes through the following build paths:
Using an obfuscator that does things like removing dead code and shortening variable and method names, such as the great ProGuard tool is an essential starting point. Another essential tool is the pack200 tool that is especially good at compressing (or preparing for compression) of jar files. Pack200 creates a “pack” file from a jar file that optimized for compression, and that may be compressed into a gzip file by pack200 itself or another compression tool. In this build chain I both let pack200 do the compressing, and also compress using 7-Zip and kzip. In fact, I run the kzip command not directly but using a script that runs kzip a number of different times and keeps the smallest result.
Setting up a compression chain such as this takes some time, but is well worth the effort when every byte counts. Which, to be honest, isn’t that often in real world situations.