Runtimes Updates Post-JDK 11 - Sip of Java

Since JDK 11 was released in September of 2018, the JDK has seen several runtime changes that improve performance and help address common issues. This article covers some key changes added to the JDK during that time.

Class-Data Sharing Updates

Class-Data Sharing (CDS) goes back to JDK 5. CDS uses a shared archive that contains pre-processed class data. If present, the JVM can load from the shared archive, improving startup performance. The shared archive is also memory mapped, and when multiple JVMs are running on the same host, they can all read from the same shared archive, reducing memory usage.

Default CDS Archive

Before JDK 12, Java developers would have to create the shared archive manually on non-Windows platforms. JEP 314 addressed this in JDK 12 as shared archives containing core JDK classes are now included on all JDK images.

Dynamic CDS Archive

In JDK 10, CDS was extended to cover application classes, AppCDS. AppCDS allows Java developers to create a shared archive that includes classes from their written application. This will enable CDS to remain relevant and beneficial in even more significant applications. Initially to create a shared archive of an application was a two-step process. The user would need to run the application to create a class list, and a second run would be required to create a shared archive based on the previously created class list.

JEP 350 in JDK 13 simplifies the creation of a shared archive to a single step, using the VM flag -XX:ArchiveClassesAtExit=<shared archive>.

Helpful NullPointerExceptions

NullPointerExceptions are a bane of all Java developers. The worst is when a NullPointerException occurs on a line where multiple reference types could be null! JEP 358, added in JDK 14, and made default by JDK 15, allows the JVM to precisely describe which variable was null. An example of what the new NullPointerException message looks like can be seen here:

Exception in thread "main" java.lang.NullPointerException: 
        Cannot assign field "i" because "a" is null
    at Prog.main(

Note: There is some performance overhead for this feature and possibly some security issues with how the JVM might print a message. Helpful NullPointerExceptions can be disabled with -XX:-ShowCodeDetailsInExceptionMessages.


ZGC is a fundamental redesign of garbage collection in Java. ZGC was initially introduced as an experimental feature in JDK 11 (JEP 333). In JDK 15, JEP 377, ZGC was designated as a product feature.

ZGC was designed with the goals of low-latency, initially targeting sub-10ms pause times, which as of JDK 16 is now < 1ms, and the ability to scale up to multi-terabyte heap sizes (16TB). The G1 garbage collector remains the default GC; ZGC can be enabled with the VM flag: -XX:+UseZGC .

Performance Updates

Every release of the JDK sees many performance improvements across many factors; startup, throughput, latency, memory usage, and others. Most of these changes don’t raise to the level of a JEP. Nevertheless, the compound effect of all these changes starts to become significant after many releases.

Because every application, system architecture, and business needs are different, it can’t be concretely predicted the performance improvements that will come from upgrading your runtime to the latest JDK, but if on JDK 11 or earlier, the benefits should be measurable.

To see how your application(s) might benefit from upgrading runtimes, profile them using a tool like JDK Flight Recorder (JFR) to provide a detailed analysis of what is happening within the JVM and application at runtime. This can also help track down any issues due to updating runtimes.

Additional Reading

Happy coding!