GraalJS

GraalJS 是基於 GraalVM 建構的快速 JavaScript 語言實作。它符合 ECMAScript 標準,提供與 Java 和其他 Graal 語言的互通性、常見工具,並且如果使用 GraalVM JDK 執行,則預設會透過 Graal JIT 編譯器提供最佳效能。您也可以將 GraalJS 與 Oracle JDK 或 OpenJDK 搭配使用。

對於想要從 Nashorn 或 Rhino 遷移到支援新 ECMAScript 標準和功能的 JavaScript 引擎的專案,GraalJS 是合適的替代方案。您可以輕鬆地將 GraalJS 新增到您的 Java 應用程式,如下所示。

在 JVM 上開始使用 GraalJS #

若要在 Java 主機應用程式中嵌入 JavaScript,請將 GraalJS 新增為專案相依性來啟用它。所有必要的成品都可以直接從 Maven Central 下載。所有與嵌入器相關的成品都可以在 Maven 相依性群組org.graalvm.polyglot中找到。

以下是 JavaScript 嵌入的 Maven 設定

<dependency>
    <groupId>org.graalvm.polyglot</groupId>
    <artifactId>polyglot</artifactId>
    <version>${graaljs.version}</version>
</dependency>
<dependency>
    <groupId>org.graalvm.polyglot</groupId>
    <artifactId>js</artifactId>
    <version>${graaljs.version}</version>
    <type>pom</type>
</dependency>

這會啟用 GraalJS,它是基於 Oracle GraalVM 建構,並根據GraalVM 免費條款和條件 (GFTC)授權。如果您想使用基於 GraalVM 社群版的 GraalJS,請使用 artifactId js-community 而不是 js

逐步建立一個 Maven 專案,將 JavaScript 嵌入到 Java 中並執行它。此範例應用程式已使用適用於 JDK 23 的 GraalVM 和 GraalVM Polyglot API 版本 24.1.0 進行測試。請參閱下載頁面,了解如何安裝 GraalVM。

  1. 在您最愛的 IDE 中或從終端機使用以下結構建立一個名為「helloworld」的新 Maven Java 專案
     ├── pom.xml
     └── src
         ├── main
         │   └── java
         │       └── com
         │           └── example
         │               └── App.java
    

    例如,您可以執行此命令,使用 quickstart 原型建立新的 Maven 專案

     mvn archetype:generate -DgroupId=com.example -DartifactId=helloworld -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.5 -DinteractiveMode=false
    
  2. App.java 的內容替換為以下程式碼
     package com.example;
    
     import org.graalvm.polyglot.*;
     import org.graalvm.polyglot.proxy.*;
    
     public class App {
    
         static String JS_CODE = "(function myFun(param){console.log('Hello ' + param + ' from JS');})";
    
         public static void main(String[] args) {
             String who = args.length == 0 ? "World" : args[0];
             System.out.println("Hello " + who + " from Java");
             try (Context context = Context.create()) {
                 Value value = context.eval("js", JS_CODE);
                 value.execute(who);
             }
         }
     }
    

    此範例應用程式使用Polyglot API,並以 Java 值傳回 JavaScript 函式。

  3. 將以下相依性新增到 pom.xml 以包含 JavaScript 引擎 (GraalJS)
     <dependencies>
         <dependency>
             <groupId>org.graalvm.polyglot</groupId>
             <artifactId>polyglot</artifactId>
             <version>${graaljs.version}</version>
         </dependency>
         <dependency>
             <groupId>org.graalvm.polyglot</groupId>
             <artifactId>js</artifactId>
             <version>${graaljs.version}</version>
             <type>pom</type>
         </dependency>
     </dependencies>
    

    透過將 graaljs.version 屬性新增到 <properties> 區段來設定 GraalJS 和 GraalVM Polyglot API 版本。或者,您可以直接用版本字串替換 ${graaljs.version}。在此範例中,使用 24.1.0

     <properties>
         <graaljs.version>24.1.0</graaljs.version>
     </properties>
    
  4. 將 Maven 外掛程式新增到您的 pom.xml 檔案,以將專案編譯成 JAR 檔案,並將所有執行階段相依性複製到目錄中
     <build>
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <version>3.13.0</version>
                 <configuration>
                     <fork>true</fork>
                 </configuration>
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-jar-plugin</artifactId>
                 <version>3.4.2</version>
                 <configuration>
                     <archive>
                         <manifest>
                             <mainClass>com.example.App</mainClass>
                         </manifest>
                     </archive>
                 </configuration>
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-dependency-plugin</artifactId>
                 <version>3.8.0</version>
                 <executions>
                     <execution>
                         <id>copy-dependencies</id>
                         <phase>package</phase>
                         <goals>
                             <goal>copy-dependencies</goal>
                         </goals>
                         <configuration>
                             <outputDirectory>${project.build.directory}/modules</outputDirectory>
                             <includeScope>runtime</includeScope>
                             <includeTypes>jar</includeTypes>
                         </configuration>
                     </execution>
                 </executions>
             </plugin>
         </plugins>
     </build>
    
  5. (選用。)將 module-info.java 新增到您的應用程式。如果您想在模組路徑上執行您的應用程式,請在 src/main/java 中建立一個 module-info.java 檔案,其中包含以下內容
     module com.example {
         requires org.graalvm.polyglot;
     }
    
  6. 編譯並封裝專案
     mvn clean package
    
  7. 使用 GraalVM 或其他相容的 JDK 執行應用程式。如果您已在專案中包含 module-info.java (步驟 5),您現在可以使用以下其中一個命令,在模組路徑上執行應用程式
    java --module-path target/modules:target/helloworld-1.0-SNAPSHOT.jar --module com.example/com.example.App "GraalVM"
    java -p target/modules:target/helloworld-1.0-SNAPSHOT.jar -m com.example/com.example.App "GraalVM"
    

    否則,您可以使用模組路徑上的相依性和類別路徑上的應用程式來執行

    java --module-path target/modules --add-modules=org.graalvm.polyglot -cp target/helloworld-1.0-SNAPSHOT.jar com.example.App "GraalVM"
    java --module-path target/modules --add-modules=org.graalvm.polyglot -jar target/helloworld-1.0-SNAPSHOT.jar "GraalVM"
    

    或者,您也可以使用類別路徑上的所有內容來執行 (在這種情況下,您需要使用 * 或指定所有 JAR 檔案)

    java -cp "target/modules/*:target/helloworld-1.0-SNAPSHOT.jar" com.example.App "GraalVM"
    # or using shell expansion:
    java -cp "$(find target/modules -name '*.jar' | tr '\n' :)target/helloworld-1.0-SNAPSHOT.jar" com.example.App "GraalVM"
    java -cp "$(printf %s: target/modules/*.jar)target/helloworld-1.0-SNAPSHOT.jar" com.example.App "GraalVM"
    

    注意:我們不建議將所有相依性捆綁到單一的「胖」JAR 中 (例如,使用 Maven Assembly 外掛程式),因為這可能會導致問題,並阻止使用GraalVM Native Image進行預先編譯。相反地,我們建議對所有 org.graalvm.* 相依性使用原始、單獨的 JAR 檔案,最好是在模組路徑上。請在嵌入語言指南中了解更多資訊。

原始程式碼單元可以使用字串表示,如範例所示、從檔案中讀取、從 URL 中讀取,以及其他方式。藉由包裝函式定義 (()),您可以立即傳回函式

Value f = context.eval("js", "(function f(x, y) { return x + y; })");
Value result = f.execute(19, 23);

您也可以從 JavaScript 查閱 Java 類型並將其具現化,如下所示

try (Context context = Context.newBuilder()
                           .allowHostAccess(HostAccess.newBuilder(HostAccess.ALL).build())
                           .allowHostClassLookup(className -> true)
                       .build()) {
    java.math.BigDecimal v = context.eval("js",
            "var BigDecimal = Java.type('java.math.BigDecimal');" +
            "BigDecimal.valueOf(10).pow(20)")
        .asHostObject();
    assert v.toString().equals("100000000000000000000");
}

Polyglot API 提供了許多其他方法,可從 Java 存取客座語言程式碼,例如,直接存取 JavaScript 物件、數字、字串和陣列。請在Java 互通性指南中了解更多關於 JavaScript 到 Java 互通性的資訊,並尋找更多範例。

GraalJS 也以獨立發行版提供,您可以從GitHub下載。請在此處了解更多資訊。

我們為 GraalJS 使用者提供以下文件

遷移指南

了解更多關於從舊版環境遷移的資訊

與我們聯繫