*Really* Small Java Apps :: Mar 4, 2019
Since bundling apps and runtime is the new best-practice (whether with Docker or jpackage), and the full JVM weighs in at hundreds of megabytes, how can we include only the minimal JVM subset our application requires? This post explores 4 complementary ways:
- Build a minimal JDK image
- Use jlink to create an application image
- Choose a minimal docker image
- Use the jlink image with jpackage
Building the JDK
OpenJDK has many features, including 7 Garbage Collectors (Epsilon, Serial, Parallel, CMS, G1, Shennandoah, ZGC!!) and experimental compilers like Graal. Building the OpenJDK is suprisingly easy (took 12 minutes for a fresh build on my 2015 macbook), so lets strip out what we don’t need!
We care about two
--with-jvm-features=<feature>[,<feature>...]. By default
configure uses the
server variant, which includes features:
aot: experimental ahead of time compilation
cds: class Data Sharing
cmsgc: concurrent mark sweep gc
compiler1: the C1 compiler
compiler2: the C2 compiler
dtrace: support for the tracing framework
epsilongc: a no-op gc
g1gc: the garbage-first garbage collector
graal: experimental C2 replacement written in Java
jfr: Java Flight Recorder support
jni-check: Java Native Interface support
jvmci: the compiler interface needed for Graal and other plugin-in JITs
jvmti: tools interface for debuggers and profilers
management: app monitoring/management support with Java Management Extensions
nmt: Native Memory Tracking
parallelgc: the Parallel GC
serialgc: the Serial GC
services: not really sure.. maybe the ServiceProvider api?
shenandoahgc: Shenandoah GC
vm-structs: for servicability agents
The other varients are server, client, minimal, core, zero, and custom.
minimal comes with compiler1, dtrace, and serialgc.
My app doesn’t need most of this, so I build a minimal JDK with C1, C2, DTrace, G1GC, and CDS (for quicker startup, requires G1GC):
Configure should spit out something like
You can now use
jlink, etc from the build output.
If your app uses the Java Module System, it’s easy to make a minimal JRE image, with just the modules you require:
Make sure not to use compress=2, since your applicationn will be slower, AND larger (at least for now).
There are early-access builds of jpackage available. Jlinked images can be specified with an option.
For a simple project requiring java.net.http, using these steps produced a 23MB jlink image. Hopefully this can be improved further if jlink improves –compress=2 to use LZ4 (https://twitter.com/shipilev/status/1100396679285665794)