2

I am experimenting with running JS scripts from Java code within a GraalVM native-image.

The Java code looks like this:

try (Context context = Context.create("js")) {
    Value bindings = context.getBindings("js");
    bindings.putMember("response", response);
    bindings.putMember("UTF8", StandardCharsets.UTF_8);
    context.eval("js", script);
} catch (PolyglotException e) {
    error("Error: " + e, 10);
}

The JS code just tries to use the response object by calling a method on it, for example:

 print("Status code: " + response.getStatusCode());

This works when running in GraalVM, but when creating a native-image, it fails with this error:

INVOKE on JavaObject[...] failed due to: Message not supported: INVOKE

If I just print the object as in print("Response: " + response);, it does not fail. But if I attempt to call any method on response, I get this error (even toString() or hashCode()).

Is there something else I need to do or is this just a bug in SubstractVM native-image, currently?

My GraalVM version:

java version "1.8.0_172"
Java(TM) SE Runtime Environment (build 1.8.0_172-b11)
GraalVM 1.0.0-rc4 (build 25.71-b01-internal-jvmci-0.45, mixed mode)

native-image command I am using:

native-image --language:js --report-unsupported-elements-at-runtime -jar my.jar
1
  • I've done more investigations and found out I was using the GraalVM API wrong. I should be using getPolyglotBindings() instead of getBindings("js"), and should do response = Polyglot.import('response'); on the JS side before using response... Still, it won't work in native-image, only on the normal GraalVM. Commented Aug 5, 2018 at 13:27

1 Answer 1

5

Update: as of RC 13 reflective access with native image is now supported. You need to provide a reflection config to native image.

Unfortunately GraalVM, as of RC5, doesn't yet support reflective access of Java objects when compiled using native-image. We plan to support this in one of the next release candidates.

As a temporary workaround you may use the Proxy API like this:

try (Context context = Context.create("js")) {
    Map<String, Object> myObject = new HashMap<>();
    myObject.put("foo", "bar");
    context.getBindings("js").putMember("hostObject", ProxyObject.fromMap(myObject));
    assert "bar".equals(context.eval("js", "hostObject.foo").asString());
    myObject.put("foo", "baz");
    assert "baz".equals(context.eval("js", "hostObject.foo").asString());
}

The Proxy API allows to mimic guest language values.

Here is another Proxy Example: http://www.graalvm.org/docs/graalvm-as-a-platform/embed/#computed-arrays-using-polyglot-proxies

Proxy Javadoc: http://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/proxy/package-summary.html

Sign up to request clarification or add additional context in comments.

1 Comment

We full support this now and we have dedicated docs for this: graalvm.org/reference-manual/embed-languages/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.