Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
openjdk version "11.0.5" 2019-10-15
OpenJDK Runtime Environment (build 11.0.5+10-jvmci-19.3-b05-LTS)
OpenJDK 64-Bit GraalVM CE 19.3.0 (build 11.0.5+10-jvmci-19.3-b05-LTS, mixed mode, sharing)
Case 1:
import org.graalvm.polyglot.Context;
public class Test {
static class Data {
public String name = "HelloWorld";
public String getName() {
return this.name;
public static void main(String[] args) {
Context context = Context.newBuilder("js").allowHostAccess(true).build();
context.getBindings("js").putMember("d", new Data());
context.eval("js", "var x = d.name");
System.out.println(
context.getBindings("js").getMember("x").asString()
Result:
As I can understand, d passed correctly:
((Data) context.getBindings("js").getMember("d").as(Data.class)).name
returns "HelloWorld".
Case 2:
context.eval("js", "d.getName()");
Exception
Exception in thread "main" TypeError: invokeMember (getName)
on JavaObject[task.Test$Data@35a3d49f (task.Test$Data)] failed due to:
Unknown identifier: getName
But getName is public...
What's wrong?
When you use a context and add a Java Object to it, behind the scene, the IntropLibrary inside TruffleApi creates a HostObject and associate it with that object. This means that you don't use the object itself but rather a wrapper object.
When you call the getMember() method, the IntropLibrary can only access fields and methods of the hosted object that are publicly available. Since your inner class has default access (no access modifier), the API cannot find its members even though they are public. (a member of a class cannot have broader access than its class itself).
To solve this issue, all you have to do is make you inner class public
import org.graalvm.polyglot.Context;
public class Test {
public static class Data {
public String name = "HelloWorld";
public String getName() {
return this.name;
public static void main(String[] args) {
Context context = Context.newBuilder("js").allowHostAccess(true).build();
context.getBindings("js").putMember("d", new Data());
context.eval("js", "var x = d.name;");
System.out.println(
context.getBindings("js").getMember("x").asString()
By default only public classes, methods, and fields that are annotated with @HostAccess.Export are accessible to the guest language. This policy can be customized using Context.Builder.allowHostAccess(HostAccess) when constructing the context.
Example using a Java object from JavaScript:
public class JavaRecord {
@HostAccess.Export public int x;
@HostAccess.Export
public String name() {
return "foo";
Alternatively, you can use GraalVM JSR-223 ScriptEngine
GraalVM JavaScript provides a JSR-223 compliant javax.script.ScriptEngine implementation. Note that this is feature is provided for legacy reasons in order to allow easier migration for implementations currently based on a ScriptEngine. We strongly encourage users to use the org.graalvm.polyglot.Context interface
To set an option via Bindings, use Bindings.put(, true) before the engine's script context is initialized. Note that even a call to Bindings#get(String) may lead to context initialization. The following code shows how to enable polyglot.js.allowHostAccess via Bindings:
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
bindings.put("polyglot.js.allowHostAccess", true);
bindings.put("polyglot.js.allowHostClassLookup", (Predicate<String>) s -> true);
bindings.put("javaObj", new Object());
engine.eval("(javaObj instanceof Java.type('java.lang.Object'));"); // would not work
without allowHostAccess and allowHostClassLookup
This example would not work if the user would call e.g. engine.eval("var x = 1;") before calling bindings.put("polyglot.js.allowHostAccess", true);, since any call to eval forces context initialization.
–
GraalVM JavaScript enforces strict sandboxing rules by default, one of them being that JavaScript code cannot access host Java objects unless it is explicitly allowed by the user. The simplest way to allow your code to access context.eval("js", "d.getName()") is to pass the option polyglot.js.allowAllAccess=true as described in below link:
GraalVM JavaScript ScriptEngine implementation
Have a look at the Sample:
import org.graalvm.polyglot.Context;
public class Test {
static class Data {
public String name = "HelloWorld";
public String getName() {
return this.name;
public static void main(String[] args) {
Context context = Context.newBuilder("js").allowHostAccess(true).build();
context.getBindings("js").putMember("d", new Data());
context.eval("js", "var x = d.getName()");
System.out.println(
context.getBindings("js").getMember("d").as(Data.class)).name
–
To get full access to a java object in the usual js way, you can use the sj4js library.
This example is taken from the documentation...
public class TestObject extends JsProxyObject {
// the property of the object
private String name = "";
// the constructor with the property
public TestObject (String name) {
super ();
this.name = name;
// we hvae to initialize the proxy object
// with all properties of this object
init(this);
// this is a mandatory override,
// the proxy object needs this method
// to generate new objects if necessary
@Override
protected Object newInstance() {
return new TestClass(this.name);
// the setter for the property name
public void setName (String s) {
this.name = s;
// the getter for the property name
public String getName () {
return this.name;
And you can access this object as you would access a java object.
try (JScriptEngine engine = new JScriptEngine()) {
engine.addObject("test", new TestClass("123"));
engine.exec("test.name");
// returns "123"
engine.exec("test['name']")
// returns "123"
engine.exec("test.name = '456'")
engine.exec("test.name");
// returns "456"
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.