Ahead-of-time Compilation

GraalVM allows you to compile your programs ahead-of-time into a native executable. The resulting program does not run on the Java HotSpot VM, but uses necessary components like memory management, thread scheduling from a different implementation of a virtual machine, called Substrate VM. Substrate VM is written in Java and compiled into the native executable. The resulting program has faster startup time and lower runtime memory overhead compared to a Java VM.

Currently, native images work mainly for JVM-based languages, e.g., Java, Scala, Clojure, Kotlin. The resulting image can, optionally, execute dynamic languages like Ruby, R, or Python, but it does not pre-compile their code itself.

For example you can take a look at the native image generation or compiling a Java and Kotlin app ahead-of-time samples.

Prerequisites

To build a native image of your program use the native-image utility located in the bin directory of the GraalVM distribution. For compilation native-image depends on the local toolchain, so please make sure: glibc-devel, zlib-devel (header files for the C library and zlib) and gcc are available on your system.

Image Generation Options

The native-image command line needs to provide the class path for all classes using the familiar option from the java launcher: -cp is followed by a list of directories or .jar files, separated by :. The name of the class containing the main method is the last argument; or you can use -jar and provide a .jar file that specifies the main method in its manifest.

Go over the native-image command line options that may be useful:

  • native-image [options] class builds an executable file for a class in the current working directory. Invoking it executes the native-compiled code of that class.

  • native-image [options] -jar jarfile builds an image for a jar file.

You may provide additional options to native-image building:

  • -cp and --class-path <class search path of directories and zip/jar files> help to search for class files through separated list of directories, JAR archives, and ZIP archives;

  • --shared builds shared library;

  • --static builds statically linked executable (requires static libc and zlib) (since 1.0-rc2);

  • --delay-class-initialization-to-runtime=<comma separate list of class names> delays class initialization to runtime for given classes and their subclasses (since 1.0-rc6);

  • -D<name>=<value> sets a system property;

  • -J<flag> passes <flag> directly to the JVM running the image generator;

  • -g enables debug info generation;

  • -O<level> 0 - no optimizations, 1 - basic optimizations (default);

  • -ea enables assertions in the generated image;

  • --verbose enables verbose output;

  • --version prints product version and exits;

  • --help prints the help message;

  • --help-extra prints the help message on non-standard options;

  • --report-unsupported-elements-at-runtime reports usage of unsupported methods and fields at run time when they are accessed the first time, instead of as an error during image building.

Macro Options

Macro-options are mainly helpful for polyglot capabilities of native images:

  • --language:python to make sure Python is available as a language for the image;

  • --language:llvm to make sure LLVM bitcode is available for the image;

  • --language:js to make sure JavaScript is available as a language for the image;

  • --language:ruby to make sure Ruby is available as a language for the image;

  • --tool:chromeinspector adds truffle debugging support to a truffle-language image;

  • --tool:profiler adds truffle profiling support to a truffle-language image.

Non-standard Options

Get acquainted with the non-standard native-image building options, that are subject to change without notice:

  • --no-server tells to not use image-build server;

  • --server-list lists current image-build servers;

  • --server-list-details lists current image-build servers with more details;

  • --server-cleanup removes stale image-build servers entries;

  • --server-shutdown shutdowns image-build servers under current session ID;

  • --server-shutdown-all shutdown all image-build servers;

  • --server-session=<custom-session-name> uses custom session name instead of system provided session ID of the calling process;

  • --debug-attach[=<port>] attaches to debugger during image building (default port is 8000);

  • --dry-run outputs the command line that would be used for image building;

  • --expert-options lists image build options for experts;

  • --expert-options-all lists all image build options for experts (to be used at your own risk);

  • --configurations-path <search path of option-configuration directories> a separated list of directories to be treated as option-configuration directories.

If the environment variable NATIVE_IMAGE_CONFIG_FILE is set to a Java properties file, native-image will use the defaults defined in there on each invocation.

Here is an example of configuration file (saved as ~/.native-image/default.properties) :

NativeImageArgs = --no-server \
                  --configurations-path /home/user/custom-image-configs

If the user has this configuration file and export NATIVE_IMAGE_CONFIG_FILE=$HOME/.native-image/default.properties in ~/.bash_profile, every time the native-image gets used, it will implicitly use the arguments specified as NativeImageArgs, plus the arguments specified on command line.

For a more comprehensive list of options please check the documentation on Github.

Generating Heap Dumps

GraalVM also supports monitoring and generating heap dumps of the native image processes. This functionality is available in the Enterprise edition of GraalVM. It is not available in the Community edition of GraalVM.

To find out more about generating heap dumps of the native image processes, refer to the step-by-step documentation.

Limitations of AOT Compilation

To achieve such aggressive ahead-of-time optimizations, we run an aggressive static analysis that requires a closed-world assumption. We need to know all classes and all bytecodes that are reachable at run time. Therefore, it is not possible to load new classes that have not been available during ahead-of-time-compilation.

For a more detailed description of which features of Java are not supported by the native images or supported partially please refer to the documentation on the GitHub. And if you’re interested in learning about the support for Java reflection, there’s a special document for Java reflection support.

Operational information for native images

When does it make sense to run native images instead of the JVM?

  • When startup time and memory footprint is important.
  • When you want to embed Java code with existing C/C++ applications

What is the typical performance profile on the SVM?

  • Right now peak performance is a bit worse than HotSpot, but we don’t want to advertise that (and we want to fix it of course).

What tools work with SVM: debugger, profilers? How to use them?

  • The community version does not support DWARF information. The enterprise version supports all native tools that rely on DWARF information, like debuggers (gdb) and profilers (VTune).