Oracle Labs has released GraalVM 21.1 featuring experimental binaries for Java 16. This new release also contains performance improvements along with new features, such as support for multiple locales in a Native Image. Node.js, originally included in previous versions of the GraalVM installation package, is now an optional dependency requiring manual installation.
The GraalVM Community Edition binaries, based on OpenJDK, have been updated to Java 8u292, 11.0.11 and 16.0.1, and the GraalVM Enterprise Edition binaries, based on Oracle JDK, have been updated to Java 8u291, 11.0.11, 16.0.1. Both editions supporting Java 16 may be used for testing and evaluation, but are still under development. There are three known issues for JDK 16 when generating a Native Image: an unexpected method:proxyClassLookup
error might occur when building a native image with default proxy methods; an jdk.vm.ci.common.JVMCIError: Unknown JvmConstant tag 17
error is raised when lambda expressions in classes are initialized at runtime, and support for JDK Flight Recorder (JFR) is not available. Several other tools, such as VisualVM, are already JDK 16 compatible. VisualVM is now compatible with Apple’s M1 chip.
The new version of the Visual Studio Code (VS) Extensions visualizes unit test results and offers support for refactoring Java code. First introduced in GraalVM 19.2, various features have been added including the Micronaut VS Code Extension, support for YAML and Docker builds, and assistance for configuration files and Java code.
Similar to the native-image
utility with the release of GraalVM 19.0, Node.js has become an optional dependency which requires manual installation and is no longer enabled by default. It may be installed with the GraalVM updater utility, gu
, by invoking the command gu install nodejs
. As a result, the community edition downloads are about 50 MB smaller. The JavaScript runtime is still included in the GraalVM installation.
GraalVM community edition builds for MacOS based on OpenJDK 8 are no longer being produced. The Linux AArch64 builds are still experimental, but include the GraalVM compiler, gu
tool, Node.js, Native Image and some developer tools.
The compiler was further optimized to eliminate unnecessary memory barriers for sequential volatile writes on x86 processors. When inlining code, numerous volatile writes may occur in sequence. The compiler will now drop the memory barriers except for the last write in the sequence, which increases the performance of methods such as ConcurrentHashMap.transfer()
.
Another optimization is the elimination of casts to Node.js for loaded array elements. This was necessary when volatile fields were loading from arrays and lost type information about the element. In the following example the cast, (Node<K,V>)
, is no longer required:
static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
}
Support for locales is improved such that multiple locales may be used in a Native Image. Developers may specify which locales to include during build time. Specific locales may be added with -H:IncludeLocales=en,nl
and all locales may be added with -H:+IncludeAllLocales
. The default locale is specified with -H:DefaultLocale=ja
.
Multitier compilation improves warmup time and is now enabled by default for the Polyglot Runtime used by Truffle languages such as JavaScript, Python and Java on Truffle. The first tier is optimized for compilation speed and uses method inlining for trivial methods. The second tier uses all of GraalVM’s optimizations. The new experimental compilation queue feature further improves warmup time and may be enabled with --engine.TraversingCompilationQueue
.
Several improvements have been made after Java on Truffle was added in GraalVM 21.0. Debugging is now faster as enabling the instrumentation no longer causes issues. Shutdown hooks in the application are now executed as expected when the application ends.
Java applications can take advantage of the guest Java Polyglot API provided by Java on Truffle. For example, the Context.safepoint()
method may be used to poll thread-local actions while a host method is running. The Context
class may be used to check for an interrupt or cancellation. An experimental feature for HotSpot provides the ability to specify the maximum heap memory to limit the memory usage of the guest Truffle language. This is invoked with: --sandbox.MaxHeapMemory=<size>
. The Java Polyglot API now supports data structures comparable to byte buffer, iterator, iterable and map. After the various guest languages implement these features, they work like their native features.
Several enhancements for loops are available in the enterprise edition. The compiler can now detect and vectorize loops with a hashcode pattern, where the hash is calculated similar to c * hash + array[i]
. Inverted loops, such as a do-while loop, are now optimized just as other loops with guard optimization, vectorization, full unrolling and partial unrolling. Tests have demonstrated performance improvements by up to forty percent. A check is performed for every iteration of a while loop, and an ArrayIndexOutOfBoundsException
is thrown if the index is higher than the array length. GraalVM optimizes that part by extracting the verification and placing it before the loop. However, that means a verification is always performed, even if the loop isn’t entered. GraalVM solves that issue by using an inverted loop.
Further details on these new features may be found in Unboxing the GraalVM 21.1 release! presented by Oleg Šelajev, lead developer advocate for GraalVM and Thomas Wuerthinger, GraalVM founder and project lead.