GraalVM 21.0: Introducing a New Way to Run Java

Oleg Šelajev
Jan 19 · 6 min read

Today we’re happy to announce the GraalVM 21.0 release.

With the recent winter holidays break this release was in development for a brief time, however it still offers a number of improvements and new exciting features for the whole GraalVM ecosystem.

As with every release, we’re greatly thankful to the wonderful GraalVM community for all the feedback, collaboration and the discussions around the issues, sending pull requests, and last but not least spreading the word about the GraalVM project and how it helps your project. Together, we make GraalVM extraordinary!

GraalVM 21.0 is available for downloading right now:

In this article we want to talk about some of the most notable changes in GraalVM 21.0. There are many components to GraalVM and every release brings improvements and fixes to all of them. So for a more detailed list of changes, please consider the release notes on the website or the change logs of the individual components.

Platform Updates

As usual, the release bumps up the version of the JDK used for the GraalVM builds. GraalVM Community Edition in 21.0 is based on OpenJDK version 1.8.0_282 and OpenJDK version 11.0.10, and the GraalVM Enterprise on Oracle JDK version 1.8.0_281 and Oracle JDK version 11.0.10.

Java on Truffle

The most exciting addition in GraalVM 21.0 is the new component which implements Java on Truffle. Java on Truffle is a JVM, realized with the Truffle framework.

Image for post
Image source: Jess Eddy, Unsplash

Java on Truffle is currently marked as experimental. However, even in this initial release state it offers very interesting capabilities and makes Java (and other JVM languages) possible to run through the infrastructure that powers all other GraalVM languages.

Install it with gu install espresso, and give it a spin by running your favourite Java app with java -truffle.

Read more about Java on Truffle in this adjacent article providing more details, motivation, and use cases for how you can experiment with using Java on Truffle now.

Native Image

One of the things possible now is the use of Java serialization in the native image binaries. Serialization usage needs to be configured, just like the other dynamic features, and classes which can be serialised/deserialized needs to be known during the build time. The configuration can be generated using the assisted configuration withjavaagent, so you don’t have to create it from scratch.

Consider, for example, if you have a class like this:

It serializes, deserializes and prints the Fibonacci numbers. You can compile and run it withjavaagent:

java -agentlib:native-image-agent=config-output-dir=config/META-INF/native-image Main

Now in the config directory, we can see the JSON file showing which classes will be included for serialisation:

cat config/META-INF/native-image/serialization-config.json 
[{ "name":"java.lang.Long" },
{ "name":"java.lang.Number" },
{ "name":"java.util.ArrayList" }

All that is left to build the native image is just running the command: native-image -cp .:config Main. And voila, the list of the Fibonacci numbers will be serialized/deserialized when you run the result.

In addition to this very important change that brings native image capabilities to more Java programs much easier than before, 21.0 has an improved method handle invocation support. Most of the use cases of method handles should be working now. They do require the configuration, but the tracing agent can also provide it for you.

Speaking of the configuration agent with the configuration provided by it, you can build native images of the AWT and Swing applications on Linux (experimental). Other platforms aren’t supported yet, but it’s an excellent first step.


Truffle added the HostCompilerDirectives annotation for directives that guide the optimizations in host compilations of the Truffle interpreters:

  • HostCompilerDirectives.BytecodeInterpreterSwitchto denote methods that contain the instruction-dispatch switch in bytecode interpreters
  • HostCompilerDirectives.BytecodeInterpreterSwitchBoundary to denote methods that do not need to be inlined into the bytecode interpreter switch.


Node.js in the distributions of GraalVM got updated to 12.20.1.

Compatibility is always priority number one, and this release enables the following ECMAScript 2021 mode/features by default:

  • Class fields
  • Promise.any
  • String.prototype.replaceAll
  • Logical Assignment Operators

Even more, if you would run the JavaScript engine in the ECMAScript 2022 mode enabled by the --js.ecmascript-version=2022 option, you even get the implementation of the relative indexing method proposal.


In GraalVM 21.0, the Ruby implementation now targets compatibility with Ruby 2.7.2. Most Ruby 2.7 features and changes are implemented (see this GitHub issue for the details).

In addition to that, in the short time this release was in development, there were some performance improvements, notably methods like MatchData#length, Array#sample, String#inspect, are now more efficient.

A few issues around the $~ special variable were also fixed.

Some interop method under Truffle::Interop have been renamed to match better the naming of InteropLibrary (#2139).

Note that the new IRB version is quite slow when copy/pasting code into it. This is due to an inefficient io/console implementation which will be addressed in the next release. A workaround is to use irb --readline, which disables some IRB features but is much faster for copy/pasting code.


The team continues to work on the compatibility both with Python native libraries and the Jython implementation.

For example, 21.0 saw the addition of the jarray module for compatibility with Jython. It also sports fixes to avoid possible memory leaks and crashes when running NumPy in certain setups and improved support for Pandas.

For more details about the performance updates, and other fixes, check out the changelog in the repo.

LLVM bitcode runtime

One of the major areas for improvement for the LLVM bitcode runtime implementation is warmup. In 21.0 we improved not only the AST sharing — sharing the internal representation of the program among several contexts in a single engine, but also introduced support for the auxiliary engine caching. On top of what the AST sharing provides, the auxiliary engine caching allows persisting of shared code across process boundaries.


The Webassembly interpreter sometimes flies under the radar, but there’s always active work happening to make it better, faster, and more secure. In 21.0 we optimized the Graalwasm interpreter making the warmup better and overall peak performance of interpreting WebAssembly up to 20x faster. We also pass most of the official WebAssembly specification suite now, and we are working on fixing several minor remaining edge-cases.


Since GraalVM 21.0 the gu utility becomes more powerful and can be used to update your local GraalVM installation to a newer version, or upgrade from the Community to Enterprise Edition. Please refer to the documentation for more details.

Also, as a part of the GraalVM 21.0 release, we’re happy to announce the GraalVM Extension Pack for Visual Studio Code. While being a Technology Preview release, it already provides many features to boost your Java 8+, JavaScript, Python, Ruby, R, and Micronaut productivity in the VS Code environment. The Extension Pack is immediately available on the Visual Studio Code Marketplace and ready to be installed right from your VS Code — just type GraalVM in the Extensions: Marketplace view, select the GraalVM Extension Pack and click the Install button. While installing, you can read more details on the VS Code extensions in a separate article.

Note that these are only a part of the improvements in the GraalVM 21.0! Please read a more detailed outline of the new and noteworthy features in the release notes, and for the components you’re most interested in the changelogs are an invaluable source of information!

As we mentioned before, the downloads are available as always for GraalVM 20.3.1 and GraalVM Enterprise 20.3.1.

Even if you don’t plan to upgrade right now, which you should, grab the binaries and try Java on Truffle, it is a really cool addition to the ecosystem.

Please don’t hesitate to let us know on any and all feedback! There are several channels available to reach the team, pick whichever works for you best: Slack, GitHub, or Twitter!

— GraalVM Team


GraalVM team blog -

Oleg Šelajev

Written by

Developer advocate for GraalVM at OracleLabs. VirtualJUG organizer. Became Java Champion in 2017. Likes programming languages, compilers, performance, chess



GraalVM team blog -

Oleg Šelajev

Written by

Developer advocate for GraalVM at OracleLabs. VirtualJUG organizer. Became Java Champion in 2017. Likes programming languages, compilers, performance, chess



GraalVM team blog -

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store