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.

Comments:

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 04: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 06:12 AM 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 27, 2008 at 08:11 PM EDT #

what about performances ?
How having rt.jar compressed or not, indexed or not will impact JVM perfs ?

Posted by Zeugme on May 14, 2008 at 11:34 PM 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 18, 2008 at 05:22 PM 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 03: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 25, 2008 at 09:40 PM 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 01:30 AM EDT #

Great info. Apart from the (legally) bit!
The law is a pain somethimes isn't it!?

Posted by vardis on December 01, 2008 at 11:48 PM 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 03:18 AM EST #

useful post. thanks for sharing

Posted by barackoli on April 22, 2009 at 02:04 PM EDT #

How do I cancel email notifications? The only comments posted are spam.

Posted by Dmitry Leskov on January 10, 2010 at 04:15 PM EST #

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.

Posted by mbtshoeos on June 01, 2010 at 02:07 PM EDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Jim Connors

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today