GraalVM, a polyglot virtual machine that provides a shared runtime to execute applications written in multiple languages, has released major version 22.0 with many native image improvements. The updated native image builder utility comes with significant improvements to speed up build times, reduce image sizes, and utilize less memory to build and run images. Driven by feedback from the community, the output from the utility now provides deep insights into the image generation process.
The native image builder, native-image
, now encodes the stack frame metadata in a compressed format to reduce the image size. Furthermore, the enterprise edition uses an optimized String.format()
that makes localization classes unreachable when appropriate, thereby significantly reducing image sizes.
By default, the generated native images will now use the Serial Garbage Collector (Serial GC). Serial GC is optimized for low memory footprint and small Java heap sizes. It reduces the time spent in GC and/or the resident set size (RSS) of the application. Note that Serial GC is a good choice for small heaps. For applications that require larger heaps, the G1 GC could be a better choice but is only available in the enterprise edition.
Prior to this release, it has been observed that the native image builds tend to be slower, especially in docker/kubernetes environments. With version 22.0 and upwards, the native-image
’s default output provides key information throughout the image generation process that is split across multiple stages.
As can be seen from the screenshot above, the output is now cleanly separated into multiple stages with progress bars where applicable. Each *
in the progress bar is an iteration of the analysis done during image generation. The performance analysis stage is a key area to identify misconfigurations. Reviewing the output can help the user find overly broad class paths that can result in a large number of unused classes and methods. Potential overuse of reflection can also be identified from the output. As one can guess, removing unused jars and avoiding reflection when possible can improve build times and reduce image sizes. The image creation stage is another key area whose output can be reviewed to further reduce the image size and speed up the builds. A resource usage report is generated at the end of the build that shows the time spent in garbage collection, the peak RSS, and the CPU load. All these various stats can be used to speed up the builds by fine tuning available memory and CPU. The generated report can also be visually analyzed by loading it into the GraalVM dashboard.
And thanks to its closed world analysis technique, native-image
can now detect and report security vulnerabilities. During the performance analysis stage of a build, any known security vulnerabilities on the classpath
will get flagged. The following screenshot shows the output from native-image
where it flags the usage of an unpatched log4j library and the vulnerable methods.
Image Source: GraalVM 22.0 Release Stream
The native image support for the Java Module System has also been improved in this release. In addition to supporting --add-reads
and --add-modules
, all module related options are now considered prior to scanning the modulepath
. These improvements will help prevent class loading errors and allow for better module introspection at run time.
Note that this is the final release where the native-image
can be run with JDK 8. In fact, GraalVM 22.0 enterprise edition has dropped JDK 8 support and is based on JDK 11 and JDK 17. The Java versions in this release of GraalVM community edition are based on OpenJDK 11.0.14 and OpenJDK version 17.0.2.
GraalVM 22.0 also includes new and updated compiler optimizations like partial unrolling, inlining, duplication, and vectorization. The enterprise edition has a new loop rotation optimization which is disabled by default. The enterprise edition’s Graal compiler can now do optimizations even in the absence of profiles. Both the community and enterprise editions ship with a native image optimization for switch statements that use instanceof
branches.
As usual, this release of GraalVM comes with compatibility and runtime improvements across its Python, R, Ruby, and LLVM distributions. GraalVM’s implementation of the WebAssembly language and Java on Truffle have both improved their compatibility with the Truffle framework. The Node.js distribution of GraalVM got updated to 14.18.1. And GraalVM’s JavaScript will have ECMAScript 2022 mode and features enabled by default.
On a final note, GraalVM 22.0 release comes with an improved GraalVM Extension Pack for Visual Studio Code to assist in the development and debugging of GraalVM based applications.