- Why GraalVM?
- Getting Started
- Release Notes
- Reference Manual
- GraalVM Updater
- JVM Languages Reference
- LLVM Languages Reference
- Python Reference
- R Reference
- Ruby Reference
- Scala Reference
- Polyglot Reference
- Embedding Reference
- Tools Reference
- Native Image
- Security Guide
- GraalVM as a Platform
GraalVM Native Image
GraalVM Native Image allows you to ahead-of-time compile Java code to a standalone executable, called a native image. This executable includes the application, the libraries, the JDK and does not run on the Java VM, but includes necessary components like memory management and thread scheduling from a different virtual machine, called “Substrate VM”. Substrate VM is the name for the runtime components (like the deoptimizer, garbage collector, thread scheduling etc.). The resulting program has faster startup time and lower runtime memory overhead compared to a Java VM.
Native Image Generator or
native-image is a utility that processes all the classes of your application and their dependencies, including those from the JDK. It statically analyses these classes
to determine which classes and methods are reachable and used during application
execution. Then it passes all this reachable code as the input to the GraalVM
compiler which ahead-of-time compiles it to the native binary.
native-image supports JVM-based languages, e.g., Java, Scala,
Clojure, Kotlin. The resulting native image can, optionally, execute dynamic
languages like Ruby, R, or Python, but it does not pre-compile their code
itself. Polyglot embeddings can also be compiled ahead-of-time. To inform
native-image of guest languages used by an application, specify
--language:<languageId> for each guest language used (e.g.,
Warning: GraalVM Native Image is available as an Early Adopter technology, meaning it can be used in production and will be supported by Oracle as part of the Oracle GraalVM Enterprise Edition subscription, but is not covered by Oracle’s standard warranty.
Install Native Image
Starting from GraalVM 19.0, Native Image was extracted from the base distribution. This functionality can be added to the core installation with GraalVM Updater tool in a similar way as other additional components by running:
gu install native-image
After this additional step, the
native-image executable will be in the
directory, as for the previous releases.
native-image depends on the local toolchain, so please make
zlib-devel (header files for the C library and
gcc are available on your system.
Another prerequisite to consider is the maximum heap size. Physical memory for
running a JVM-based application may be insufficient to build a native image. For
server-based image building we allow to use 80% of the reported physical RAM for
all servers together, but never more than 14GB per server (for exact details
please consult the native-image source code). If you run with
option, you will get the whole 80% of what is reported as physical RAM as the
baseline. This mode respects
-Xmx arguments additionally.
Image Generation Options
native-image command line needs to provide the class path for all classes
using the familiar option from the
-cp is followed by a list
of directories or .jar files, separated by
:. The name of the class containing
main method is the last argument; or you can use
-jar and provide a .jar
file that specifies the main method in its manifest. The syntax of the
native-image command is:
native-image [options] classto build 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 jarfileto build an image for a jar file.
There is a command-line help available. Run
native-image --help to get
commands overview and
native-image --help-extra to print help on non-standard
You may provide additional options to the native image building:
--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;
-D<name>=<value>sets a system property for the JVM running the image generator;
<flag>directly to the JVM running the image generator;
-O<level>0 – no optimizations, 1 – basic optimizations (default);
-daenables or disables assertions in the generated image;
--allow-incomplete-classpathallows image building with an incomplete class path and reports type resolution errors at run time when they are accessed the first time, instead of during image building;
--auto-fallbackbuilds a stand-alone image if possible, which is a default setting,
--no-fallbackbuilds a stand-alone image or reports a failure, and
--force-fallbackforces building of a fallback image;
--enable-all-security-servicesadds all security service classes to the generated image;
--enable-httpsenables http or https support in the generated image;
--enable-url-protocolsprovides a list of comma separated URL protocols to enable;
--featuresprovides a comma-separated list of fully qualified feature implementation classes;
--initialize-at-build-time=<comma separated list of class/package names>initializes classes and implicitly all of their superclasses during image building;
--initialize-at-run-time=<comma separated list of class/package names>initializes classes and implicitly all of their superclasses at run time and not during image building;
--report-unsupported-elements-at-runtimereports usage of unsupported methods and fields at run time when they are accessed the first time, instead of as an error during image building;
--sharedbuilds shared library;
--staticbuilds statically linked executable (requires static libc and zlib) (since 1.0-rc2);
--verboseenables verbose output;
-genables the debugging info generation. Warning: The option is available only with GraalVM Enterprise Edition.
Macro-options are mainly helpful for polyglot capabilities of native images:
--language:nfito make Truffle Native Function Interface language available;
--language:regexto make Truffle Regular Expression engine available that exposes regular expression functionality in GraalVM supported languages;
--language:pythonto make sure Python is available as a language for the image;
--language:llvmto make sure LLVM bitcode is available for the image;
--language:rubyto make sure Ruby is available as a language for the image;
--language:Rto make sure R is available as a language for the image;
--tool:chromeinspectoradds debugging support to a Truffle framework based language image;
--tool:profileradds profiling support to a Truffle framework based language image.
Please note, the
--language:R polyglot macro options become available once the corresponding languages engines are added to the base GraalVM installation with GraalVM Updater tool:
gu install python gu install ruby gu install R
Get acquainted with the non-standard native image building options, that are subject to change through a deprecation cycle:
--no-servertells to not use server-based image building;
--server-listlists current image-build servers;
--server-list-detailslists current image-build servers with more details;
--server-cleanupremoves stale image-build servers entries;
--server-shutdownshuts down image-build servers under current session ID;
--server-shutdown-allshuts down all image-build servers;
--server-session=<custom-session-name>uses custom session name instead of system provided session ID of the calling process;
--verbose-serverenables verbose output for image-build server handling.
--debug-attach[=<port>]attaches to debugger during image building (default port is 8000);
--dry-runoutputs the command line that would be used for image building;
--expert-optionslists image build options for experts;
--expert-options-alllists 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;
-V<key>=<value>provides values for placeholders in native-image.properties files.
If the environment variable
NATIVE_IMAGE_CONFIG_FILE is set to a Java
properties file, a native image will use the defaults defined in there on each
Here is an example of configuration file (saved as
NativeImageArgs = --configurations-path /home/user/custom-image-configs \ -O1
If the user has a configuration file and export
~/.bash_profile, every time the native image gets used, it will implicitly use the arguments
NativeImageArgs, plus the arguments specified on command line.
For a more comprehensive list of options please check the documentation on Github.
Warning: Python source code or LLVM bitcode interpreted or compiled with GraalVM Community Edition will not have the same security characteristics as the same code interpreted or compiled using GraalVM Enterprise Edition. There is a GraalVM string embedded in each image that allows to figure out the version and variant of the base (Community or Enterprise) used to build an image. The following command will query that information from an image:
strings <path to native-image exe or shared object> | grep com.oracle.svm.core.VM
Assuming you have a Java class file EmptyHello.class containing an empty main method
and have generated an empty shared object
emptyhello with GraalVM Native Image Generator utility of it:
$ native-image -cp hello EmptyHello Build on Server(pid: 11228, port: 41223) [emptyhello:11228] classlist: 149.59 ms ...
If you do not know what GraalVM distribution is set to the
variable, how to determine if a native image was compiled with Community or
Enterprise Edition? Run this command:
$ strings emptyhello | grep com.oracle.svm.core.VM
The expected output should match the following:
com.oracle.svm.core.VM GraalVM 19.2.0 CE
For additional performance gain and higher throughput in GraalVM
ahead-of-time (AOT) mode, make use of profile-guided optimizations (PGO). With
PGO, you can collect the profiling data in advance and then feed it to the
native-image utility, which will use this information to optimize the
performance of the resulting binary.
Warning: Profile-guided optimizations (PGO) is a GraalVM Enterprise feature.
In GraalVM versions prior to 19.2.0, a commonly used technique to mitigate the
missing just-in-time (JIT) optimization is to gather the execution profiles at one run
and then use them to optimize subsequent compilation(s). In other words, one
needs to create a native image with the
--pgo-instrument option to collect the
profile information. The
--pgo-instrument builds an instrumented native image
with profile-guided optimization data collected of AOT compiled code
in the default.iprof file, if nothing else is specified. Then you run an
example program, saving the result in default.iprof. Finally, you create a
second native image with
--pgo profile.iprof flag that should be significantly
Starting from 19.2.0, you can collect profiles while running your application in JIT mode and then use this information to generate a highly-optimized native binary. This maximizes the performance even more.
- Run a java program in JIT mode with a
-Dgraal.PGOInstrumentflag to gather the profiling information:
$ java -Dgraal.PGOInstrument=myclass.iprof MyClass
- Use the collected data to generate a native image:
$ native-image --pgo=myclass.iprof MyClass
- Run the resulting binary:
Generating Heap Dumps
GraalVM also supports monitoring and generating heap dumps of the Native Image processes.
Warning: This functionality is available in the Enterprise 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 are interested in learning about the support for Java reflection, there is a separate document for Java reflection support.
Operational Information for Native Images
When does it make sense to run in a Native Image 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 tools work with Native Image: 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).