With the GraalVM Polyglot API you can embed and run code from a guest language in a Java-based host application. GraalVM makes it possible to compile a Java application ahead-of-time with embedded JavaScript and to create a polyglot native executable. See the Embedding Languages documentation for more information about how a Java host application can interact with a guest language like JavaScript.
This guide demonstrates how to build a polyglot native executable with Java as a host language and JavaScript as a guest language.
For the demo part, you will use a simple JSON Pretty Printer Java application that prints the output in JSON format.
Make sure you have installed a GraalVM JDK. The easiest way to get started is with SDKMAN!. For other installation options, visit the Downloads section.
Create a Maven project and replace the default Application.java file with a file named PrettyPrintJSON.java. Copy and paste the following contents into the file:
import java.io.*;
import java.util.stream.*;
import org.graalvm.polyglot.*;
public class PrettyPrintJSON {
public static void main(String[] args) throws java.io.IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String input = reader.lines()
.collect(Collectors.joining(System.lineSeparator()));
try (Context context = Context.create("js")) {
Value parse = context.eval("js", "JSON.parse");
Value stringify = context.eval("js", "JSON.stringify");
Value result = stringify.execute(parse.execute(input), null, 2);
System.out.println(result.asString());
}
}
}
Open your project configuration file (in this case, pom.xml) and add the following dependencies to enable interoperability with JavaScript.
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>polyglot</artifactId>
<version>${graalvm.version}</version>
</dependency>
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>js</artifactId>
<version>${graalvm.version}</version>
</dependency>
./mvnw clean package
native-image PrettyPrintJSON
It takes several minutes as it does not just build the executable, but also pulls in the JavaScript engine. The JavaScript context will be available in the generated image.
Note: Building a polyglot native executable requires more physical memory because the Truffle framework is included.
./prettyprintjson <<EOF
{"GraalVM":{"description":"Language Abstraction Platform","supports":["combining languages","embedding languages","creating native images"],"languages": ["Java","JavaScript","Node.js", "Python", "Ruby","R","LLVM"]}}
EOF
The expected output is:
{
"GraalVM": {
"description": "Language Abstraction Platform",
"supports": [
"combining languages",
"embedding languages",
"creating native images"
],
"languages": [
"Java",
"JavaScript",
"Node.js",
"Python",
"Ruby",
"R",
"LLVM"
]
}
}
The native executable version runs faster than running the same application on the GraalVM JDK.
Note: JavaScript support by GraalVM Native Image is considered general availability. The remaining languages support is experimental.