Hands-on with OpenJ9 benefits for Spring applications
Improve memory overhead and startup times
The Eclipse OpenJ9 JVM offers Spring applications significant benefits when deployed as part of a cloud-native runtime. OpenJ9 comes with improvements to memory overhead and startup times, achieved through shared classes and an aggressive focus on memory footprint.
To benefit from the startup time improvements, enable OpenJ9’s SharedClasses Cache (which enables dynamicAOT), by setting the following JVM options:
-Xshareclasses -Xscmx50M -Xquickstart
Hands on exploration of benefits
To explore these memory overhead and startup times benefits yourself, you can run Spring’s petclinic demo, using Docker to test with OpenJDK and OpenJ9, enabling you to see for yourself the differences between the two runtimes. We’ve supplied a collection of Dockerfiles to make this really simple to do.
You can check the memory footprint for the petclinic app by following these steps:
Get the Dockerfiles.
Build each of the docker images:
docker build -f Dockerfile.openj9 -t=demo.openj9 docker build -f Dockerfile.openjdk -t=demo.openjdk
From a spare command prompt, run the OpenJ9 image, and note the startup time:
docker run --rm -it demo.openj9
From another spare command prompt, run the OpenJDK image, and note the startup time:
docker run --rm -it demo.openjdk
Finally, from another command prompty, run:
docker ps docker kill <id>
Here’s the output from
docker stats, showing OpenJ9 (
af0c33faf180, on the first line) using only around 1/3 of the memory that OpenJDK uses when running Spring’s petclinic sample application:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS af0c33faf180 serene_tereshkova 0.95% 153.7MiB / 1.952GiB 7.69% 718B / 0B 85.3MB / 4.1kB 42 8abb2874bed9 pedantic_darwin 0.65% 469.2MiB / 1.952GiB 23.48% 718B / 0B 80.7MB / 0B 36
Memory footprint has always been a focus for the OpenJ9 JVM, and there are a lot of reasons why OpenJ9 is smaller:
- Size of the class meta data
- Smaller default heap sizes
- Less aggressive Java heap expansion
- An overall consistent focus during development on retaining a small memory footprint.
You can check the startup times for the petclinic app by following these steps:
Get the Dockerfiles.
Build the docker image:
docker build -f Dockerfile.openj9.cold -t=demo.openj9.cold
Launch the docker image:
docker run --rm -it demo.openj9.cold
This image has sharedclasses enabled so that OpenJ9’s class meta data (J9ROMClass) can be saved in the cache as well as AOT & JIT hints.
The startup will typically be slower in the “cold” run, as the cache is being filled.
Build the new image with the cache filled.
Save the last image using:
docker commit <id> demo.openj9.warm
Run the image with the cache filled:
docker run --rm -it demo.openj9.warm
The footprint should be equivalent to the earlier runs, but with a faster startup. This is mostly due to AOT relocation being much faster than JIT compilation (in the order of 10-100x).