GraalVM JavaScript Implementation
GraalVM provides an ECMAScript-compliant runtime to execute JavaScript and Node.js applications.
It is fully standard compliant, executes applications with high performance, and provides all benefits from the GraalVM stack, including language interoperability and common tooling.
This reference documentation provides information on available JavaScript engine configurations, the Node.js runtime, the javax.script.ScriptEngine
implementation, multithreading support details, possible embedding scenarios, and more.
To migrate the code previously targeted to the Nashorn or Rhino engines, migration guides are available.
Running JavaScript
Since GraalVM 22.2, the JavaScript support is packaged in a separate GraalVM component. It can be installed with the GraalVM Updater:
$JAVA_HOME/bin/gu install js
Alternatively, you can download the JavaScript component and install it from a file, e.g.:
$JAVA_HOME/bin/gu install --file ~/Downloads/js-...-.jar
This installs js
in the $JAVA_HOME/bin
directory.
When the JavaScript component is installed, GraalVM can run plain JavaScript (ECMAScript) code:
$JAVA_HOME/bin/js [options] [filename...] -- [args]
For information about the compatibility of GraalVM JavaScript with existing standards and engines, see JavaScriptCompatibility.
Running Node.js
GraalVM is capable of executing unmodified Node.js applications. Applications can import npm modules, including native ones. Since GraalVM 21.1, the Node.js support is packaged in a separate GraalVM component. It can be installed with the GraalVM Updater:
$JAVA_HOME/bin/gu install nodejs
Alternatively, you can download the Node.js component and install it from a file, e.g.:
$JAVA_HOME/bin/gu install --file ~/Downloads/nodejs-installable-...-.jar
This installs node
and npm
launchers in the $JAVA_HOME/bin
directory.
Use the node
utility to execute Node.js applications:
node [options] [filename] [args]
To install a Node.js package, use the npm
launcher from $JAVA_HOME/bin
.
The npm
command is equivalent to the default Node.js command and supports all Node.js APIs.
- Install the
colors
andansispan
packages usingnpm install
as follows:npm install colors ansispan
After the packages are installed, you can use them from your application.
- Add the following code snippet to a file named
app.js
and save it in the same directory where you installed the Node.js packages:const http = require("http"); const span = require("ansispan"); require("colors"); http.createServer(function (request, response) { response.writeHead(200, {"Content-Type": "text/html"}); response.end(span("Hello Graal.js!".green)); }).listen(8000, function() { console.log("Graal.js server running at http://127.0.0.1:8000/".red); }); setTimeout(function() { console.log("DONE!"); process.exit(); }, 2000);
- Execute it on GraalVM using the
node
command as follows:node app.js
For more information about running Node.js, continue to Node.js Runtime.
Node.js functionality is available when an application is started from the node
binary launcher.
Certain limits apply when launching a Node.js application or accessing npm packages from a Java context, see Node.js vs. Java Script Context.
Interoperability
GraalVM supports several other programming languages like Ruby, R, Python, and LLVM languages. While GraalVM is designed to run Node.js and JavaScript applications, it also provides interoperability between those languages and lets you execute code from or call methods in any of those languages using GraalVM Polyglot APIs.
To enable Node.js or JavaScript interoperability with other languages, pass the --jvm
and --polyglot
options. For example:
node --jvm --polyglot
Welcome to Node.js v16.14.2.
Type ".help" for more information.
> var array = Polyglot.eval("python", "[1,2,42,4]")
> console.log(array[2]);
42
> console.log(Polyglot.eval('R', 'runif(100)')[0]);
0.8198353068437427
For more information about interoperability with other programming languages, see Polyglot Programming for a general description.
Interoperability with Java
To access Java from JavaScript, use Java.type
, as in the following example:
node --jvm
> var BigInteger = Java.type('java.math.BigInteger');
> console.log(BigInteger.valueOf(2).pow(100).toString(16));
10000000000000000000000000
Vice versa, you can execute JavaScript from Java by embedding the JavaScript context in the Java program:
import org.graalvm.polyglot.*;
import org.graalvm.polyglot.proxy.*;
public class HelloPolyglot {
static String JS_CODE = "(function myFun(param){console.log('hello '+param);})";
public static void main(String[] args) {
System.out.println("Hello Java!");
try (Context context = Context.create()) {
Value value = context.eval("js", JS_CODE);
value.execute(args[0]);
}
}
}
By wrapping the function definition (()
), you return the function immediately.
The source code unit can be represented with a String, as in the example, a file, read from URL, and other means.
Run the above Java program:
javac HelloPolyglot.java
java HelloPolyglot JavaScript
This way you can evaluate JavaScript context embedded in Java, but you will not be able to call a function and set parameters in the function directly from the Java code. The Node.js runtime cannot be embedded into a JVM but has to be started as a separate process.
For example, save this code as app.js:
var HelloPolyglot = Java.type("HelloPolyglot");
HelloPolyglot.main(["from node.js"]);
console.log("done");
Then start node
with the --jvm
option to enable interoperability with Java:
node --jvm --vm.cp=. app.js
Hello Java!
hello from node.js
done
By setting the classpath, you instruct node
to start a JVM properly.
Both Node.js and JVM then run in the same process and the interoperability works using the same Value
classes as above.
Learn more about language interoperability in the Java Interoperability guide.
Further documentation
For additional information, refer to those documentation pages on specific topics around GraalVM JavaScript:
Using GraalVM JavaScript:
- JavaScript Compatibility
- Options and Flags to the Engine
- Multithreading Support
- Java Interoperability
- Execute GraalVM JavaScript on a Stock JDK
Legacy environments:
Node.js support: