Get started with GraalVM – a high-performance runtime that provides significant improvements in application performance and efficiency which is ideal for microservices. It is designed for applications written in Java, JavaScript, LLVM-based languages such as C and C++, and other dynamic languages. It removes the isolation between programming languages and enables interoperability in a shared runtime. This page guides you through downloading and installing GraalVM Community and adding support for additional languages or components and shows you how to run simple programs.

GraalVM is available as GraalVM Community and GraalVM Enterprise editions. GraalVM Community editions are based on OpenJDK version 1.8.262 and on OpenJDK version 11.0.8. GraalVM Enterprise editions are based on Oracle JDK version 1.8.0_261 and on Oracle JDK version 11.0.8. GraalVM distributions are available for Linux, macOS and Windows platforms on AMD64 systems and for the Linux platform on AARCH64 systems.

GraalVM consists of core and optional components, and is distributed as an archive. Proceed to the Distribution Components List for a complete description.

Install GraalVM #

Getting GraalVM installed and ready-to-go should only take a few minutes. Choose a platform and proceed to the installation steps:

Running Applications #

In this getting started guide we will focus on working with GraalVM Community Edition based on OpenJDK 8.

The executables of all language runtimes in GraalVM emulate the behavior of the languages’ default runtimes. Setting GraalVM to the PATH and JAVA_HOME environment variables during the installation should be enough to run an application with GraalVM.

GraalVM’s /bin directory is similar to that of a standard JDK, but includes a set of additional launchers:

  • js runs a JavaScript console with GraalVM.
  • node is a drop-in replacement for Node.js, using GraalVM’s JavaScript engine.
  • lli is a high-performance LLVM bitcode interpreter integrated with GraalVM.
  • gu (GraalVM Updater) can be used to install language packs for Python, R, and Ruby.

Check the versions of the default runtimes:

$ java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (build 1.8.0_252-b09)
OpenJDK 64-Bit Server VM GraalVM CE 20.1.0 (build 25.252-b09-jvmci-20.1-b02, mixed mode)

$ node -v
v12.15.0

$ lli --version
LLVM (GraalVM CE Native 20.1.0)

The Ruby, Python, R, Wasm launchers become available only if you install the corresponding languages engines. For installing languages, see below.

Running Java #

The java launchers runs the JVM with GraalVM’s default compiler. Take a look at this typical HelloWorld class:

public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, World!");
  }
}

Run the following command to compile this class to bytecode and then run it on GraalVM:

$ javac HelloWorld.java
$ java HelloWorld
Hello World!

You can find a collection of larger examples of Java applications you can try running with GraalVM on the examples page.

Running JavaScript #

GraalVM can execute plain JavaScript code, both in REPL mode and by executing script files directly.

$ js
> 1 + 2
3

GraalVM also supports running Node.js applications. More than 100,000 npm packages are regularly tested and are compatible with GraalVM, including modules like express, react, async, request, browserify, grunt, mocha, and underscore. To install a Node.js module, use the npm executable in the /bin folder of the GraalVM package. The npm command is equivalent to the default Node.js command and supports all Node.js APIs.

1. Install the colors and ansispan modules using npm install:

npm install colors ansispan

After the modules are installed, you can use them from your application.

2. Add the following code snippet to a file named app.js and save it in the same directory where you installed the Node.js modules:

  // RUN-CMD: rm -rf node_modules
// RUN-CMD: npm install ansispan colors
// RUN-CMD: node {file}
// RUN-CMD: rm -r node_modules

// BEGIN-SNIPPET

const http = require("http");
const span = require("ansispan");
require("colors");

http.createServer(function (request, response) {
    response.writeHead(200, {"Content-Type": "text/html"});
    response.end(span("Hello Graal.js!".green));
}).listen(8000, function() { console.log("Graal.js server running at http://127.0.0.1:8000/".red); });
// END-SNIPPET

setTimeout(function() { console.log("DONE!"); process.exit(); }, 2000);
  

3. Execute it on GraalVM using the node command:

node app.js

More information on compatibility with the Node.js and configuring GraalVM read the reference manual on JavaScript in GraalVM.

Running LLVM Bitcode #

The GraalVM LLVM runtime can execute C/C++, Rust, and other programming language that can be compiled to LLVM bitcode. A native program has to be compiled to LLVM bitcode using an LLVM frontend such as clang. C/C++ code can be compiled to LLVM bitcode using clang shipped with GraalVM via a pre-built LLVM toolchain.

To set up the LLVM toolchain support, execute the following commands:

$ gu install llvm-toolchain
$ export LLVM_TOOLCHAIN=$(lli --print-toolchain-path)

Please note, the installation of the LLVM toolchain component is possible only from GitHub catalog for both GraalVM Community and Enterprise users.

Put this C code example into a file named hello.c:

#include <stdio.h>

int main() {
    printf("Hello from GraalVM!\n");
    return 0;
}

Then compile hello.c to an executable hello with embedded LLVM bitcode and run it as follows:

$ $LLVM_TOOLCHAIN/clang hello.c -o hello
$ lli hello

More examples and information on running LLVM bitcode with GraalVM can be found in the reference manual for LLVM.

Running Ruby #

The Ruby engine is not installed by default, but it can be added using GraalVM Updater:

gu install ruby

The above command will install a community version of a component from GitHub catalog. For GraalVM Enterprise users, the manual component installation is required. Then the Ruby launchers like ruby, gem, irb, rake, rdoc and ri will become available:

$ ruby [options] program.rb

GraalVM Ruby implementation uses the same options as the standard implementation of Ruby, with some additions.

$ gem install chunky_png
$ ruby -r chunky_png -e "puts ChunkyPNG::Color.to_hex(ChunkyPNG::Color('mintcream @ 0.5'))"
#f5fffa80

Using Bundler

GraalVM implementation of Ruby ships with the Bundler environment. Therefore its installation, gem install bundler, is not needed.

$ bundle exec ...

More examples and additional information on Ruby support in GraalVM can be found in the reference manual for Ruby.

Running Python #

GraalVM provides an early-stage implementation of Python 3.8.2. The Python engine is not available by default, but it can be added using GraalVM Updater:

gu install python

The above command will install a community version of a component from GitHub catalog. For GraalVM Enterprise users, the manual component installation is required. Once the Python engine is installed, GraalVM can execute Python programs:

$ graalpython
...
>>> 1 + 2
3
>>> exit()

More examples and additional information on Python support in GraalVM can be found in the reference manual for Python.

Running R #

The R engine is not installed by default, and can be added using GraalVM Updater:

gu install R

Please note, the installation of the R language component is possible only from GitHub catalog for both GraalVM Community and Enterprise users. When the R engine is installed, you can execute R scripts and use the R REPL with GraalVM:

$ R
R version 3.6.1 (FastR)
...

> 1 + 1
[1] 2

More examples and additional information on R support in GraalVM can be found in the reference manual for R.

Combine Languages #

If enabled, using the --polyglot flag, scripts executed on GraalVM can use interoperability features to call into other languages and exchange data with them.

For example, running js --jvm --polyglot example.js executes example.js in a polyglot context. If the program calls any code in other supported languages, GraalVM executes that code in the same runtime as the example.js application. For more information on polyglot applications see the polyglot documentation.

Native Images #

GraalVM can compile Java bytecode into native images to achieve faster startup and smaller footprint for your applications. The Native Image functionality is not available by default but can be easily installed. Run the following command to install Native Image in GraalVM Community:

gu install native-image

For GraalVM Enterprise users, the manual component installation is required.

The HelloWorld example from above is used here to demonstrate how to compile Java bytecode into a native image:

// HelloWorld.java
public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, World!");
  }
}

Run the following to compile the class to bytecode and then build a native image:

$ javac HelloWorld.java
$ native-image HelloWorld

This builds an executable file named helloworld in the current working directory. Invoking it executes the natively compiled code of the HelloWorld class as follows:

$ ./helloworld
Hello, World!

Polyglot Capabilities of Native Images

GraalVM Native Image Generator also makes it easy to use polyglot capabilities. Take this example of a JSON pretty-printer using the GraalVM implementation of JavaScript:

// PrettyPrintJSON.java
import java.io.*;
import java.util.stream.*;
import org.graalvm.polyglot.*;

public class PrettyPrintJSON {
  public static void main(String[] args) throws java.io.IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    String input = reader.lines().collect(Collectors.joining(System.lineSeparator()));
    try (Context context = Context.create("js")) {
      Value parse = context.eval("js", "JSON.parse");
      Value stringify = context.eval("js", "JSON.stringify");
      Value result = stringify.execute(parse.execute(input), null, 2);
      System.out.println(result.asString());
    }
  }
}

The --language:js argument ensures that the JavaScript engine is available in the generated image:

$ javac PrettyPrintJSON.java
$ native-image --language:js --initialize-at-build-time PrettyPrintJSON

The native image generation will take several minutes as it does not just build the PrettyPrintJSON class, but includes building a JavaScript engine (along with the support for partial evaluation). Additionally, the image building requires large amounts of physical memory, especially if you build an image with Truffle Language Implementation Framework included, which is exactly the case here. Memory requirements and some other limitations of ahead-of-time compilation with GraalVM are listed here.

The resulting executable can now perform JSON pretty printing:

$ ./prettyprintjson <<EOF
{"GraalVM":{"description":"Language Abstraction Platform","supports":["combining languages","embedding languages","creating native images"],"languages": ["Java","JavaScript","Node.js", "Python", "Ruby","R","LLVM"]}}
EOF

Here is the JSON output from the native executable:

{
  "GraalVM": {
    "description": "Language Abstraction Platform",
    "supports": [
      "combining languages",
      "embedding languages",
      "creating native images"
    ],
    "languages": [
      "Java",
      "JavaScript",
      "Node.js",
      "Python",
      "Ruby",
      "R",
      "LLVM"
    ]
  }
}

The native image is much faster than running the same code on the JVM directly:

$ time bin/java PrettyPrintJSON < test.json > /dev/null
real	0m1.101s
user	0m2.471s
sys	0m0.237s

$ time ./prettyprintjson < test.json > /dev/null
real	0m0.037s
user	0m0.015s
sys	0m0.016s

GraalVM Container Images

GraalVM Community container images are available for download from GitHub Packages.

As long as GitHub does not support anonymous access you need to login to the registry to authenticate against the GitHub Package server. You can authenticate to GitHub Packages with Docker using the docker login command. It is required to use a personal access token with the appropriate scopes for authentication. Learn how to generate personal access tokens here.

As a best practice, it is suggested to save your personal access token in a file locally. Then run the docker login command non-interactively so you can set the --password-stdin flag to provide a token. The following example shows how to read a token from a file and pass it to the docker login command using STDIN:

cat ~/TOKEN.txt | docker login https://docker.pkg.github.com -u USERNAME --password-stdin

Substitute USERNAME with your GitHub username and ~/TOKEN.txt with the file path to the file containing your personal access token. Once you have authenticated, there are two ways to install GraalVM Community container images published as GitHub Packages.

  1. Pull the image from GitHub with docker pull:
    docker pull docker.pkg.github.com/graalvm/container/community:latest
    
  2. Alternatively, use as the base image in Dockerfile:
    FROM docker.pkg.github.com/graalvm/container/community:latest
    

There are different GraalVM Community container images provided depending on the architecture and Java version. A complete list can be found on the All versions page. The images are named per a platform-os-jdk-version naming scheme, for example, docker.pkg.github.com/graalvm/container/community:ol8-java11-20.1.0. The images for 64-bit ARM architecture are prefixed with the arm64- tag, e.g., docker.pkg.github.com/graalvm/container/community:arm64-ol8-java11-20.1.0.

The container image is based on Oracle Linux and has GraalVM Community downloaded, unzipped and made available. It means that Java, JavaScript, Node and the LLVM interpreter are available out of the box.

You can start a container and enter the bash session with the following run command:

docker run -it docker.pkg.github.com/graalvm/container/community:20.1.0 bash

Check that java, js and other commands work as expected.

→ docker run -it docker.pkg.github.com/graalvm/container/community:20.1.0 bash
bash-4.4# java -version
openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02)
OpenJDK 64-Bit Server VM GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02, mixed mode, sharing)
bash-4.4# node
Welcome to Node.js v12.15.0.
Type ".help" for more information.
> 1 + 1
2
> process.exit()
bash-4.4# lli --version
LLVM (GraalVM CE Native 20.1.0)
bash-4.4#

Please note that the image contains only the components immediately available in the GraalVM Community distribution. However, the GraalVM Updater utility is on the PATH. You can install the support for additional languages like Ruby, R, Python or WebAssembly at will. For example, the following command installs the Ruby support (the output below is truncated for brevity):

docker run -it docker.pkg.github.com/graalvm/container/community:20.1.0 bash
bash-4.4# gu install ruby
Downloading: Component catalog
Processing component archive: Component ruby
Downloading: Component ruby
[######              ]
...

If you want to mount a directory from the host system to have it locally available in the container, use Docker volumes.

Here is a sample command that maps the /absolute/path/to/directory/no/trailing/slash directory from the host system to the /path/inside/container inside the container.

docker run -it -v /absolute/path/to/directory/no/trailing/slash:/path/inside/container docker.pkg.github.com/graalvm/container/community:20.1.0 bash

If you want to create docker images that contain GraalVM Ruby, R, or Python implementation, you can use a Dockerfile like the example below, which uses docker.pkg.github.com/graalvm/container/community:20.1.0 as the base image, installs Ruby support using the gu utility, then creates and runs a sample Ruby program.

FROM docker.pkg.github.com/graalvm/container/community:20.1.0
RUN gu install ruby
WORKDIR /workdir
RUN echo 'puts "Hello from Truffleruby!\nVersion: #{RUBY_DESCRIPTION}"' > app.rb
CMD ruby app.rb

If you put the above snippet in a Dockerfile in the current directory, you can build and run it with the following commands:

docker build -t truffleruby-demo .
...
$ docker run -it --rm truffleruby-demo
Hello from Truffleruby!
Version: truffleruby 20.1.0, like ruby 2.6.5, GraalVM CE Native [x86_64-darwin]

If you want to learn what GraalVM offers to different types of teams, read the Why GraalVM page. Some of the diverse features of GraalVM are disclosed and supported with examples in Top 10 Things To Do With GraalVM article. Or, you can examine different supported languages in action by looking at example applications. If you want to learn about the common tools GraalVM enables for the supported languages, proceed to the Tools section. If you are mostly interested in a specific language, more extensive documentation is available in the reference manual as well. If you are a language implementer or developer and looking for more depth-in coverage documentation, proceed to the User Documentation.