'GraalVM Java on truffle - NullPointerException from NFIContext.getBackend when executing Java code

I'm trying to run Java code dynamically inside a Java application using Truffle from GraalVM, without success.

Settings

I'm working on MacOs 11.5.2.

I've followed up the GraalVM JDK installation process, and installed espresso using gu install espresso.

$ java -version
openjdk version "11.0.13" 2021-10-19
OpenJDK Runtime Environment GraalVM CE 21.3.0 (build 11.0.13+7-jvmci-21.3-b05)
OpenJDK 64-Bit Server VM GraalVM CE 21.3.0 (build 11.0.13+7-jvmci-21.3-b05, mixed mode, sharing)
$ java -truffle -version
openjdk version "11.0.13" 2021-10-19
OpenJDK Runtime Environment GraalVM CE 21.3.0 (build 11.0.13+7-jvmci-21.3-b05)
Espresso 64-Bit VM GraalVM CE 21.3.0 (build 11-espresso-21.3.0, mixed mode)

I've been able to run a simple Hello World Class and Jar. And even run JavaScript code (as a string) in a Java host application.

Problem

But when I try to execute this program I get an error:

package com.host;

import java.io.IOException;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;

public class Main {
  public static void main(String[] args) throws IOException {
    Context polyglot = Context.newBuilder("java").allowAllAccess(true).build();

    Value java_lang_Math = polyglot.getBindings("java").getMember("java.lang.Math"); // <- Faulty line
    double sqrt2 = java_lang_Math.invokeMember("sqrt", 2).asDouble();
    double pi = java_lang_Math.getMember("PI").asDouble();
    System.out.println(sqrt2);
    System.out.println(pi);
  }
}

By the way, this code comes from their doc (https://www.graalvm.org/reference-manual/java-on-truffle/interoperability/#embedding-in-host-java)

But when I try to execute the code, either as a class or as a Jar, I get this error:

$ java -jar target/host-code-1.0-SNAPSHOT.jar
Exception in thread "main" org.graalvm.polyglot.PolyglotException: java.lang.NullPointerException
    at com.oracle.truffle.nfi.NFIContext.getBackend(NFIContext.java:83)
    at com.oracle.truffle.nfi.NFIRootNode.execute(NFIRootNode.java:147)
    at org.graalvm.sdk/org.graalvm.polyglot.Context.getBindings(Context.java:540)
    at com.host.Main.main(Main.java:13)
Original Internal Error:
java.lang.NullPointerException
    at com.oracle.truffle.nfi.NFIContext.getBackend(NFIContext.java:83)
    at com.oracle.truffle.nfi.NFIRootNode.execute(NFIRootNode.java:147)
    at jdk.internal.vm.compiler/org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.executeRootNode(OptimizedCallTarget.java:650)
    at jdk.internal.vm.compiler/org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.profiledPERoot(OptimizedCallTarget.java:622)
    at jdk.internal.vm.compiler/org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callBoundary(OptimizedCallTarget.java:555)
    at jdk.internal.vm.compiler/org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.doInvoke(OptimizedCallTarget.java:539)
    at jdk.internal.vm.compiler/org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callIndirect(OptimizedCallTarget.java:463)
    at jdk.internal.vm.compiler/org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.call(OptimizedCallTarget.java:444)
    at com.oracle.truffle.espresso.ffi.nfi.NFINativeAccess.loadLibraryHelper(NFINativeAccess.java:180)
    at com.oracle.truffle.espresso.ffi.nfi.NFISulongNativeAccess.loadLibrary(NFISulongNativeAccess.java:44)
    at com.oracle.truffle.espresso.ffi.NativeAccess.loadLibrary(NativeAccess.java:77)
    at com.oracle.truffle.espresso.jni.JniEnv.<init>(JniEnv.java:316)
    at com.oracle.truffle.espresso.jni.JniEnv.create(JniEnv.java:364)
    at com.oracle.truffle.espresso.runtime.EspressoContext.getJNI(EspressoContext.java:685)
    at com.oracle.truffle.espresso.runtime.EspressoContext.spawnVM(EspressoContext.java:463)
    at com.oracle.truffle.espresso.runtime.EspressoContext.initializeContext(EspressoContext.java:423)
    at com.oracle.truffle.espresso.EspressoLanguage.initializeContext(EspressoLanguage.java:144)
    at com.oracle.truffle.espresso.EspressoLanguage.initializeContext(EspressoLanguage.java:64)
    at org.graalvm.truffle/com.oracle.truffle.api.TruffleLanguage$Env.postInit(TruffleLanguage.java:3606)
    at org.graalvm.truffle/com.oracle.truffle.api.LanguageAccessor$LanguageImpl.postInitEnv(LanguageAccessor.java:301)
    at org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotLanguageContext.ensureInitialized(PolyglotLanguageContext.java:661)
    at org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotContextImpl.getBindings(PolyglotContextImpl.java:969)
    at org.graalvm.truffle/com.oracle.truffle.polyglot.PolyglotContextDispatch.getBindings(PolyglotContextDispatch.java:97)
    at org.graalvm.sdk/org.graalvm.polyglot.Context.getBindings(Context.java:540)
    at com.host.Main.main(Main.java:13)
Caused by: Attached Guest Language Frames (1)

I don't get what I've missed, and I have no clues how to solve this issue. Does anyone have an idea?



Solution 1:[1]

Java on Truffle (Espresso) have different configurations: native and JVM, single/multi context... it runs on all major OSs in at least one configuration, but not all of them.

Espresso native (without HotSpot), single context, runs in all platforms. Espresso on HotSpot and/or multi-context only works on Linux at the moment, this applies to some of the examples in the docs.

To run Espresso on HotSpot, one of the main challenges is isolating native libraries. On Linux, Espresso relies on glibc's dlmopen to load native libraries in isolated linking namespaces, this allows to load the same library twice or more, also when loading e.g. libjava, we want a fresh copy linking against Espresso's libjvm and not to HotSpot's.

We haven't found a similar isolation mechanism on Mac or Windows, though an alternative exists on Android.

To overcome this limitations, the team is actively working on a Sulong native backend for Espresso. Sulong is a high-performance LLVM bitcode interpreter for GraalVM. The idea is to compile the OpenJDK native libraries to LLVM bitcode and load/run them on Sulong, which by design support isolation; there's already a working prototype.

In the current state, Espresso tries to use the Sulong native backend on MacOS by default, but it's not fully functional/shipped yet, thus the error.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mukel