The simplest way to build espresso is to use a pre-built GraalVM.
Download and unpack the latest GraalVM release or ea build.
Set the JAVA_HOME environment variable to the extracted result. This will be used during the build and as a host JDK.
Espresso is only a JVM and it needs a JDK to use as a guest. Set the ESPRESSO_JAVA_HOME to a JDK to be used for the guest.
To build, run:
$ mx buildIt is also possible to build using native-image built from sources from the current graal repository.
Set your (JVMCI-enabled) JDK via mx argument e.g. mx --java-home /path/to/java/home ... or via export JAVA_HOME=/path/to/java/home. Or (easiest) run mx fetch-jdk to download one.
Set the ESPRESSO_JAVA_HOME to a JDK to be used for the guest.
Build using one of the provided configuration:
$ mx --env jvm build # GraalVM CE + Espresso jars (interpreter only)
$ mx --env jvm-ce build # GraalVM CE + Espresso jars (JIT)
$ mx --env native-ce build # GraalVM CE + Espresso native (JIT)mx build-ing Espresso creates "espresso standalones" which are JDK-like directories.
If you are only trying to build a specific one it's possible to specify it while building:
$ mx --env native-ce build --targets=ESPRESSO_NATIVE_STANDALONEConfiguration files: mx.espresso/{jvm,jvm-ce,native-ce}
You can find out where the espresso standalones are by running mx path --output ...:
$ mx path --output ESPRESSO_NATIVE_STANDALONE
$ mx path --output ESPRESSO_JVM_STANDALONENote: If you used options like
--env ...or--dynamicimports ...while building, you should also use them withmx path: e.g.,mx --env native-ce path ....
mx espresso runs Espresso from a standalone (jvm or native). It mimics the java command.
$ mx --env jvm-ce build # Always build first
$ mx --env jvm-ce espresso -cp my.jar HelloWorldTo build and run Espresso native image:
$ mx --env native-ce build # Always build first
$ mx --env native-ce espresso -cp my.jar HelloWorldThe mx espresso launcher adds some overhead, to execute Espresso native image directly use:
$ mx --env native-ce build # Always build first
$ export ESPRESSO=`mx --quiet --no-warning --env native-ce path --output ESPRESSO_NATIVE_STANDALONE`/bin/java
$ time $ESPRESSO -cp my.jar HelloWorldThis is useful if you want to depend on your branch of Espresso as a regular Maven dependency, for example to compile it into a custom native image.
$ cd ../vm
$ mx --dy /espresso,/sulong maven-deploy --tags=public --all-suites --all-distribution-types --version-suite=sdk --suppress-javadocYou can now depend on the jars using a version like 24.2.1-SNAPSHOT.
For embedding, there is a jar containing all the necessary JDK resources (classes, libraries, config files, etc.).
This jar is made available to espresso through the truffle resource API.
It is the mx distribution called ESPRESSO_RUNTIME_RESOURCES and is published on maven as org.graalvm.espresso:espresso-runtime-resources-$RuntimeResourceId where $RuntimeResourceId identifies the type and version of the included JDK.
For example org.graalvm.espresso:espresso-runtime-resources-jdk21 contain Oracle JDK 21.
ESPRESSO_RUNTIME_RESOURCES contains the JDK specified through ESPRESSO_JAVA_HOME as well as the optional llvm bits specified in ESPRESSO_LLVM_JAVA_HOME.
Since we might want to distribute these resources for multiple JDK version, it is possible to produce additional runtime resource jars.
This is done by setting EXTRA_ESPRESSO_JAVA_HOMES and optionally EXTRA_ESPRESSO_LLVM_JAVA_HOMES.
Those are lists of java homes separated by a path separator.
If EXTRA_ESPRESSO_LLVM_JAVA_HOMES is specified it should contain the same number of entries and in the same order as EXTRA_ESPRESSO_JAVA_HOMES.
The JDKs set in ESPRESSO_JAVA_HOME and EXTRA_ESPRESSO_JAVA_HOMES should all have different versions.
For example to produce jdk21 and jk25 resource in addition to the version of ESPRESSO_JAVA_HOME:
$ export ESPRESSO_JAVA_HOME=/path/to/jdk26
$ export ESPRESSO_LLVM_JAVA_HOME=/path/to/jdk26-llvm
$ export EXTRA_ESPRESSO_JAVA_HOMES=/path/to/jdk21:/path/to/jdk25
$ export EXTRA_ESPRESSO_LLVM_JAVA_HOMES=/path/to/jdk21-llvm:/path/to/jdk25-llvm
# subsequent build and maven-deploy operation will now publish
# * org.graalvm.espresso:espresso-runtime-resources-jdk21
# * org.graalvm.espresso:espresso-runtime-resources-jdk25
# * org.graalvm.espresso:espresso-runtime-resources-jdk26The org.graalvm.espresso:java maven dependency automatically depends on the "main" runtime resource (the one from ESPRESSO_JAVA_HOME).
In order to use a different version in an embedding, an explicit dependency to org.graalvm.espresso:espresso-runtime-resources-$RuntimeResourceId should be added.
The context should also be created with java.RuntimeResourceId set to the desired version (e.g., "jdk21").
To run Espresso on a vanilla JDK and/or not within a standalone use mx espresso-embedded ..., it mimics the java command. The launcher adds all jars and properties required to run Espresso on any vanilla JDK.
To debug Espresso:
$ mx build
$ mx -d espresso-embedded -cp mxbuild/dists/jdk1.8/espresso-playground.jar com.oracle.truffle.espresso.playground.HelloWorld$ mx --env jvm-ce espresso --vm.Djdk.graal.Dump=Truffle:2 --vm.Dpolyglot.engine.TraceCompilation=true -cp mxbuild/dists/jdk1.8/espresso-playground.jar com.oracle.truffle.espresso.playground.TestMainBy default, Espresso runs within a GraalVM and it reuses the jars and native libraries shipped with GraalVM. But it's possible to specify a different Java home, even with a different version; Espresso will automatically switch versions regardless of the host JVM.
$ mx build
$ mx espresso -version
$ mx espresso --java.JavaHome=/path/to/java/8/home -version
$ mx espresso --java.JavaHome=/path/to/java/11/home -versionTo run Espresso without native access, use the experimental option java.NativeBackend=no-native via the command line:
$ mx espresso --experimental-options --java.NativeBackend=no-native or on the context builder:
builder.allowExperimentalOptions(true).option("java.NativeBackend", "no-native") Disabling native access enhances security guarantees and sandboxing capabilities. In this mode, substitutions are used for Java's standard libraries, and virtualized memory will be provided (GR-70643). However, some functionality might be limited (e.g. you will have no access to LibAWT).
Espresso relies on glibc's dlmopen to run on HotSpot, but this approach has limitations that lead to crashes e.g. libnio.so: undefined symbol: fstatat64 . Some of these limitations can be by avoided by defining LD_DEBUG=unused e.g.
$ LD_DEBUG=unused mx espresso -cp mxbuild/dists/jdk1.8/espresso-playground.jar com.oracle.truffle.espresso.playground.TetrisNothing like dlmopen is available on macOS. Instead we default to nfi-staticlib for the JVM mode, which statically links in (most) of the OpenJDK libraries into libjvm.dylib.
A notable exception is libawt.dylib and its related libraries, which only work via dynamic loading.
This means in practice only the host or the guest can use AWT, but not both at the same time.
Currently nfi-staticlib only works for one Espresso context. Using nfi-staticlib with more than one context will likely result in a SIGSEGV in libtrufflenfi.dylib.
We are exploring how to implement support for multiple contexts (GR-71082).
Espresso can run itself. Self-hosting requires a Linux distribution with an up-to-date glibc.
Use mx espresso-meta to run programs on Espresso². Ensure to prepend LD_DEBUG=unused to overcome a known glibc bug.
To run HelloWorld on Espresso² execute the following:
$ mx build
$ LD_DEBUG=unused mx --dy /compiler espresso-meta -cp my.jar HelloWorldIt takes some time for both (nested) VMs to boot, only the base layer is blessed with JIT compilation. Enjoy!