Frist, Let’s talk about why our service module is migrating from the Groovy engine to the JS engine?
1). To match platform, the JS engine is used uniformly;
2). The JDK8 Nashorn engine is inferior to the JDK11 GraalVM engine for performance reasons.Yes, GraalVM JavaScript is as fast as Nashorn–up to 6x faster!
You can see[Nashorn removal: GraalVM to the rescue!]: https://medium.com/graalvm/nashorn-removal-graalvm-to-the-rescue-d4da3605b6cb.
Know GraalVM
GraalVM takes a different approach, using a single virtual machine to support different languages.The GraalVM base is a Java HotSpot virtual machine based on the OpenJDK.The Graal Compiler is a just-in-time (JIT) Compiler implemented based on the JVM Compiler Interface to translate Java bytecode into local machine code.The source code for Java and other JVM languages such as Groovy, Kotlin, and Scala runs directly on GraalVM’s Java virtual machine after being translated into Java bytecode.The Truffle framework for creating other language implementations is included in GraalVM.GraalVM’s support for JavaScript, Ruby, Python, R, and C/C++ languages is based on the Truffle framework.Truffle framework is an open language implementation framework.Other languages can run on GraalVM through the Truffle framework, and even the application’s own proprietary language.
The architecture of GraalVM is as follows:


Some possible attention points
1). we use jdk11 instead of GraalVM, so we should reference jar by maven,and have to config -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler enable graal compilerIf you need add Python/R/Ruby etc,you have two choose,frist:use GraalVM instead of JVM, second:impl interface Engine extension custom parsing.
2). JS system or customized library, You need to be careful not to repeat the name of the method, otherwise you may have method overrides and end up with an error, After all, native JS is not like other JS frameworks. In our code, third lib load by same Context, So the first load will be compiled.
3). multi-tenant solution, in our service, ervery tenant have a Context, It is automatically released when the calculation is completed. If you need, API allows code to be not cached across multiple contexts. you can see: https://www.bookstack.cn/read/graalvm/b00513b10cc379de.md
4). of course, about resource access problem: https://www.graalvm.org/reference-manual/embed-languages/#access-restrictions
It is possible to configure fine-grained access privileges for guest applications. The configuration can be provided using the Context.Builder class when constructing a new context. The following access parameters may be configured:
Allow access to other languages using allowPolyglotAccess.
Allow and customize access to host objects using allowHostAccess.
Allow and customize host lookup to host types using allowHostLookup.
Allow host class loading using allowHostClassLoading.
Allow the creation of threads using allowCreateThread.
Allow access to native APIs using allowNativeAccess.
Allow access to IO using allowIO and proxy file accesses using fileSystem.
as JS:
ok,now wo can exec test code, perform 5 times,the time key display:

In essence, the JavaScript engine of GraalVM is a plain Java application. Running it on any JVM (JDK 8 or higher) is possible, but, for a better result, it should be GraalVM or a compatible JVMCI-enabled JDK using the GraalVM compiler. This mode gives the JavaScript engine full access to Java at runtime, but also requires the JVM to first (just-in-time) compile the JavaScript engine when executed, just like any other Java application.
Running in a Native Image means that the JavaScript engine, including all its dependencies from, e.g., the JDK, is pre-compiled into a native binary. This will tremendously speed up the startup of any JavaScript application, as GraalVM can immediately start to compile JavaScript code, without itself requiring to be compiled first. This mode, however, will only give GraalVM access to Java classes known at the time of image creation. Most significantly, this means that the JavaScript-to-Java interoperability features are not available in this mode, as they would require dynamic class loading and execution of arbitrary Java code at runtime.
you can see: performance case
data access link: