A previous post on my blog demonstrated how you can, with minimal effort, lessen the disk footprint of a typical Java SE 5.0 runtime environment by about a third without violating the Java Standard Edition Licensing agreement. That post focused primarily on removing optional files and compressing class library jar files. It turns out that with a little more engineering, there is significant opportunity for further space optimization.
These additional savings involve more intimate knowledge of the inner workings of Java SE. Sun performs this engineering work and provides a series of reduced footprint versions of Java SE, in binary form, for some of the most common embedded platforms. They include some of these enhancements:
The inclusion of graphics subsystems like AWT and Swing comprise a large chunk of the Java SE footprint. If your device has no graphics capability (i.e. is headless) why would you need to include this functionality? Headless configurations:
- Do not support keyboard or mouse input
- Cannot create windows or display graphics
- Throw a HeadlessException when a graphics API is called
- Still support a functional Java 2D API for printing and off-screen rendering
- Are still 100% Java SE compatible
Eliminate client or server compiler
Sun's Java SE implementations include two HotSpot compilers, tuned and designed for specific environments. The client compiler focuses on things like fast user interactivity and quick startup, while the server compiler's priority is on optimizing large, long-lived server applications. The Java SE VM can only use one of these compilers at a time, so removing the unused one can save considerable space.
Minimizes memory consumption
Standard Java SE allocates RAM to house things like the JIT code cache and the object heap. By default, each one of these areas (and others) can be assigned 64 MB. In an embedded platform where the total amount of RAM might only be 64MB, Java SE will simply not have enough memory to run. Java SE Embedded on the other hand, will automatically adapt memory usage to the amount of available RAM. Consequently, 64MB is a reasonable amount of RAM for a large set of embedded Java applications.
Space vs. speed tradeoffs
(1) Java SE implements a thread lookup table, which in layman's terms, helps save a few instructions when switching between Java threads. By eliminating this table, a couple of MBs of RAM can be spared from your application's working set.
(2) Java SE also sets aside an area (mmap'ed) for loading jar files into random access memory, which as was explained to me, may help performance, but may also result in duplicate copies of jar files in memory. Removal of this area further reduces the Resident Set Size.
Following through with the exmaple in the last post., let's start with an unmodified version of Java SE 5.0 Update 13 for Linux/x86. By default, the static footprint is approximately 88MB.
jimc@jalopy:/tmp> du -sk ./jre1.5.0_13/
After following the directions in the previous post, we can pare it down to roughly 60MB.
jimc@jalopy:/tmp> du -sk /tmp/jre1.5.0_13/
Downloading Sun's reduced footprint version of Java SE for x86/Linux yields:
jimc@jalopy:/tmp> du -sk /tmp/jre1.5.0_10/
This version of the JRE is about one-third it's original size, and furthermore has been modified to use significantly less memory than the standard Java SE offerings. Note: we are comparing slightly different updates of Java SE 1.5 (update 13 vs. update 10). They are indeed not identical but their differences should be considered, for the sake of argument, negligible.
 Many thanks to Bob Vandette, who though presentation and conversation, supplied this information. One of many sources comes from Bob's Java ONE 2007 session called, Deploying Java Platform Standard Edition (Java SE Platform) in Today's Embedded Devices (TS-2602)
Thanks to Jim Connors for allowing the republishing of this article on JavaLobby.