使用GraalVM Polyglot加载Three.js模块

181 阅读1分钟

概述

此示例演示如何通过GraalVM的Polyglot API加载并运行JavaScript模块(如Three.js),实现Java和JavaScript的跨语言交互。

<dependency>
    <groupId>org.graalvm.polyglot</groupId>
    <artifactId>polyglot</artifactId>
    <version>24.1.1</version>
    <exclusions>
        <exclusion>
            <groupId>org.graalvm.truffle</groupId>
            <artifactId>truffle-runtime</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.graalvm.truffle</groupId>
            <artifactId>truffle-enterprise</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.graalvm.polyglot</groupId>
    <artifactId>js</artifactId>
    <version>24.1.1</version>
    <type>pom</type>
</dependency>

注意:以上依赖需要排除truffle-runtimetruffle-enterprise,以避免与模块运行时冲突。

示例代码

以下代码展示了如何使用GraalVM Polyglot API加载本地的three.module.min.js文件并与其交互:

package cn.test;

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;

import java.io.File;
import java.io.IOException;

public class App {
    public static void main(String[] args) throws IOException {
        // 确保Three.js文件存在
        File threejsFile = new File("./three.module.min.js");
        if (!threejsFile.exists()) {
            throw new RuntimeException("three.module.min.js not found");
        }

        try (
            // 创建支持JavaScript的上下文
            Context context = Context.newBuilder("js").allowAllAccess(true)
                .option("js.esm-eval-returns-exports", "true")
                .build()
        ) {
            // JavaScript代码
            String code = """
            import * as THREE from './three.module.min.js';
            const v3 = new THREE.Vector3(1, 2, 3);
            export { v3 };
          """;

            // 构建JavaScript模块
            Source source = Source.newBuilder("js", code, "three.js")
                .mimeType("application/javascript+module")
                .build();

            // 执行代码并获取结果
            Value result = context.eval(source).getMember("v3");
            System.out.println(result.toString());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

代码解析

  1. 依赖文件加载
    代码通过java.io.File确认three.module.min.js是否存在于项目根目录下。

  2. GraalVM上下文创建
    使用Context.newBuilder()配置JavaScript运行环境,支持模块导入与全访问。

    • allowAllAccess(true):允许Java与JavaScript之间的自由交互。
    • js.esm-eval-returns-exports:启用ES模块支持。
  3. 模块加载与执行
    使用Source.newBuilder()创建一个表示JavaScript模块的对象,通过context.eval()执行。

  4. 结果提取
    Value对象中提取v3,并打印其内容。

注意事项

  1. GraalVM环境
    确保安装了支持JavaScript的GraalVM版本。
  2. 文件路径
    three.module.min.js需要位于项目根目录,或者调整路径以正确加载。
  3. ESM支持
    必须启用js.esm-eval-returns-exports选项,否则模块加载可能失败。

运行结果

代码运行后,将打印THREE.Vector3实例的详细信息,表明成功加载并交互:

Vector3 { x: 1, y: 2, z: 3 }

参考文档