We started this project with the goal producing small, self-contained executables from a mix of Java and C++, targeting four platforms: Win32 (i386), Mac OS X (PPC), and Linux (i386 and amd64). GCC is an ideal tool for this purpose, since it is widely ported, and its Java and C++ compilers produce ABI-compatible object code.
However, GCC's Java compiler, GCJ, links to libgcj by default, which includes a complete Java runtime with a lot of features we don't need. Instead of trying to remove those extra features, we started from scratch, copying code from the libgcj source as necessary to allow our test code to cleanly compile, link, and run. The result is micro-libgcj.
The size and speed improvements achieved by using micro-libgcj are substantial. Consider a simple "hello, world" program (included in the distribution), linked statically against libgcj and micro-libgcj (ulibgcj), respectively, and stripped of symbols. The micro-libgcj version is about 32 times smaller and 10 times faster.
$ ls -l build/lin64/hello-* -rwxr-xr-x 1 dicej dicej 8301592 2006-01-03 16:54 build/lin64/hello-libgcj -rwxr-xr-x 1 dicej dicej 252216 2006-01-03 16:54 build/lin64/hello-ulibgcj $ time for x in $(seq 1 100); do build/lin64/hello-libgcj > /dev/null; done real 0m2.621s user 0m1.410s sys 0m1.063s $ time for x in $(seq 1 100); do build/lin64/hello-ulibgcj > /dev/null; done real 0m0.283s user 0m0.131s sys 0m0.150s $ ldd build/lin64/hello-libgcj libm.so.6 => /lib/libm.so.6 (0x00002aaaaabc3000) libpthread.so.0 => /lib/libpthread.so.0 (0x00002aaaaad48000) libdl.so.2 => /lib/libdl.so.2 (0x00002aaaaae5e000) libc.so.6 => /lib/libc.so.6 (0x00002aaaaaf61000) /lib64/ld-linux-x86-64.so.2 (0x00002aaaaaaab000) $ ldd build/lin64/hello-ulibgcj libpthread.so.0 => /lib/libpthread.so.0 (0x00002aaaaabc3000) libm.so.6 => /lib/libm.so.6 (0x00002aaaaacd8000) libc.so.6 => /lib/libc.so.6 (0x00002aaaaae5e000) /lib64/ld-linux-x86-64.so.2 (0x00002aaaaaaab000)