Jim Connors' Weblog
Reducing Your Java SE Runtime Environment Footprint (Legally)
Because the resource requirements for Java Standard Edition are by no means insignificant, developers interested in utilizing Java on smaller platforms have traditionally opted for one of the Java Micro Edition configurations. It should therefore come as no surprise that some of the Standard Edition functionality has to be sacrificed in these constrained Java ME environments. However, as the trend towards more capable devices continues, it becomes reasonable to once again consider the advantages of utilizing Java SE. Unfortunately, with a static footprint that could easily exceed 100MB, Java SE may still be too large to swallow for a lot of applications.
It is duly noted that the criticism leveled at Sun for exacting too much control
over the Java platform has been widespread. Like it or not though, one benefit of Sun's initial stewardship has been that Java SE
has remained a standard platform, and threats to splinter it have thus
far been reasonably thwarted. Accordingly, in order to avoid incompatibilities, there are restrictions spelled out in the Java SE Licensing Agreement which prohibit modification of the Java SE binary distribution.
That being said, there are a list of optional files, specified by the Java Runtime Environment's README file which can be removed, without ramification, to lessen the footprint. They include:
- Deployment tools (e.g. Java Web Start, Java plugin)
- IDL and RMI tools (e.g. rmid, tnameserv)
- Security tools (e.g. policytool, keytool)
- orbd
- Localization (charsets.jar)
In addition, further space optimization can be achieved by compressing the class library files contained in the rt.jar file. By default, Java SE ships this jar file uncompressed. The tradeoff here is space vs. performance, i.e. the classloader must expend cycles to uncompress the Java classes as they are being loaded.
An Example
So let's download a sample JRE from java.sun.com and see how it's footprint can be minimized. For this example, we'll use Java SE 1.5.0 Update 13 for Linux x86.
After installation, the JRE is approximately 88MB
jimc@jalopy:/tmp> du -sk ./jre1.5.0_13/
88185 ./jre1.5.0_13/
Here's what it looks like after removal of the optional files
jimc@jalopy:/tmp> cd jre1.5.0_13/
jimc@jalopy:/tmp/jre1.5.0_13> /bin/rm -rf lib/charsets.jar lib/ext/sunjce_provider.jar \
lib/ext/localedata.jar lib/ext/ldapsec.jar lib/ext/dnsns.jar bin/rmid \
bin/rmiregistry bin/tnameserv bin/keytool bin/kinit bin/klist bin/ktab \
bin/policytool bin/orbd bin/servertool bin/javaws, lib/javaws/ and lib/javaws.jar
jimc@jalopy:/tmp/jre1.5.0_13> cd ..
jimc@jalopy:/tmp> du -sk ./jre1.5.0_13/
77227 ./jre1.5.0_13/
And after rt.jar has been compressed
jimc@jalopy:/tmp> mkdir rtjar
jimc@jalopy:/tmp> cd rtjar/
jimc@jalopy:/tmp/rtjar> jar -xf /tmp/jre1.5.0_13/lib/rt.jar
jimc@jalopy:/tmp/rtjar> zip -q -r /tmp/rt .
jimc@jalopy:/tmp/rtjar> mv /tmp/rt.zip /tmp/jre1.5.0_13/lib/rt.jar
jimc@jalopy:/tmp/rtjar> du -sk /tmp/jre1.5.0_13/
59358 /tmp/jre1.5.0_13/
Conclusion
In many cases, you can lop off about a third of the Java Runtime Environment footprint with no ill effects. In a future post, we'll discuss how Sun has further reduced Java SE significantly, not only from the point of view of static footprint, but also from a RAM usage perspective too. For a preview you can check out Sun's Java SE Embedded technology.
Posted at 11:29AM Feb 14, 2008 by jtc in Sun | Comments[14]
Compressing rt.jar like this doesn't make much sense. Deflate isn't all that great after all. Most installers utilize LZMA is is far superior to Deflate.
The best strategy is using Pack200 (without GZip compression) and an installer which uses LZMA on top. The installer also has to take care of unpack200-ing the jars after the initial decompression. This is fairly easy with NSIS for example.
Of course this strategy is meant to reduce the size of the download. The used disk space after installation won't be affected. Well, it would be possible to recompress the jars (after un-lzma-ing and unpack200-ing). The price is a slightly longer install and slightly longer loading times. It's not that bad though - Java's deflate routines are highly optimized.
Well, 6uN (that Kernel thing) will solve most of this issue.
Posted by Jos Hirth on March 27, 2008 at 11:43 AM EDT #
Your points are quite valid with regards to installation. The theme of this post was to demonstrate how to optimize the disk footprint of an *already installed* JRE without significant re-engineering. Although a generic solution, I think these suggestions apply more to the embedded systems folks than they do to general purpose desktop/server solutions. In many instances in the embedded world, installation is done with entire images, rather than using traditional package installation.
Using zip to compress jar files is simple and universal, does shrink the the jar files by about a half, and is understood by the jar classloader. It would be cool to use even better compression, but that would require a modified classloader. If there are alternatives that the stock classloaders understand, I'd sincerely like to hear about them. If we could further reduce the on-disk footprint, that would be great.
Posted by Jim Connors on March 27, 2008 at 01:12 PM EDT #
Zip/Deflate compression can be improved by a few percent with tools like DeflOpt (formerly BJWFlate), KZip, and ZipMix. The first two just try very hard to compress the files as good as possible and ZipMix takes two zips and puts the best compressed individual files into a new zip file.
http://www.advsys.net/ken/utils.htm
http://www.walbeehm.com/download/
Obfuscators can also help quite a bit. Using multiple obfuscators can even help more. However, generally it's a "bit" on the crazy side. It's something we all did over at JGO (http://javagaming.org ) for the 4k competitions. It's only worth it if every byte counts. (But even then it's crazy.)
Well, the only kind of archives you can directly load are stored jars and deflated jars. Pack200 can be quickly added with a custom classloader. However, the format isn't suited for loading specific classes and the format itself isn't really well compressed (it's highly compressable though). While Pack200 helps compression immensely, it's only good for reducing the size of a download (applet, webstart, installer etc).
Here is some diagram of the effect of Deflate, LZMA, GZip, and Pack200 (on a pure code jar):
http://kaioa.com/svg/compression_ratio.svgz (looks better with Opera)
Some mix of LZMA and Pack200 with directly accessible files would be great, but I don't really think that's something we'll see any time soon. It's just too specific and it would be sort of slow.
Posted by Jos Hirth on March 28, 2008 at 03:11 AM EDT #
what about performances ?
How having rt.jar compressed or not, indexed or not will impact JVM perfs ?
Posted by Zeugme on May 15, 2008 at 06:34 AM EDT #
Compressing rt.jar will have some adverse effect on startup. It appears to be proportional to the clock speed of the embedded CPU. For clocks in excess of 1Ghz, this may be negligible. For slower clock cycles the effect can be modest. You mileage will vary, but we have some unofficial anecdotal evidence of 10% or more degradation in some cases. Of course you could always uncompress rt.jar and forego this space optimization altogether.
Posted by Jim Connors on May 19, 2008 at 12:22 AM EDT #
I may have a slot for a performance test un few months. I was wondering the inpact of compression knowing that disk IO are slower than memory IO. Compressing should minimize disk IO (using more CPU) and finally be quicker ...
Also I noticed on my own jar a strong impact on jar indexation that is often forgoten. I was thinking about a small loop that would rejar all JDK .jar files to ensure indexation and maybe (depending on perf result) compression or decompression (disk space doesn't really matter).
What do think about that ?
Posted by Zeugme on May 19, 2008 at 10:06 AM EDT #
There exists a more efficient Sun-approved way to reduce the Java SE footprint (though _not_ the Sun JRE footprint):
http://www.excelsior-usa.com/java-download-size.html
Posted by Dmitry Leskov on June 26, 2008 at 04:40 AM EDT #
As I know, IBM JDK does default compress their rt.jar.
Sun JRE installation package is using pack200 technology since JRE5.
I think, it as a major reason of why Sun do not compress their jar. Sun wants to provide a better "cold start" speed. The IBM JRE usually used with JEE container and "cold start" is not that important.
I had tried it few year ago, compress rt.jar in JRE1.4.2 in a old machine.
When I use the compressed JAR, it can bring quite a noticeable amount of delay during startup.
Posted by Dennis Cheung on August 29, 2008 at 08:30 AM EDT #
Great info. Apart from the (legally) bit!
The law is a pain somethimes isn't it!?
Posted by vardis on December 02, 2008 at 07:48 AM EST #
Thanks for this great post!
Posted by Busby SEO Test on December 19, 2008 at 09:25 AM EST #
thanks, I had tried it few year ago, compress rt.jar in JRE1.4.2 in a old machine.
Posted by busby seo test on December 20, 2008 at 11:18 AM EST #
Nice post. Thanks.
Posted by London Tours on January 14, 2009 at 06:09 AM EST #
useful post. thanks for sharing
Posted by barackoli on April 22, 2009 at 09:04 PM EDT #
Third ... Rosenberg says that we are opening our "competing proprietary products long after a successful open source project has eclipsed their proprietary alternatives." He then juxtaposes SPARC vs x86 as an example of this. Fascinating. I didn't know that OpenSPARC was in response to the previously open source x86 project. I must have missed that one.
http://www.watchrolexshop.com
http://www.gamegoldme.com
http://www.cheap-lotrogold.com
http://www.globalsale.me/Aion-gold-083.aspx
http://www.cheap-gamegold.org
http://www.gamegoldvip.org
Posted by replica rolex on June 25, 2009 at 02:56 AM EDT #