- GraalVM for JDK 23 (最新)
- GraalVM for JDK 24 (アーリーアクセス)
- GraalVM for JDK 21
- GraalVM for JDK 17
- アーカイブ
- 開発ビルド
ScriptEngineの実装
GraalJSは、JavaScriptを実行するためのJSR-223準拠のjavax.script.ScriptEngine
実装を提供します。この機能は、現在ScriptEngine
に基づいている実装の移行を容易にするために、レガシーの理由で提供されていることに注意してください。多くの設定を直接制御し、GraalVMのより詳細なセキュリティ設定の恩恵を受けるには、org.graalvm.polyglot.Context
インターフェースを使用することを強くお勧めします。
注:JDK 21以降のGraalVMには、デフォルトで
ScriptEngine
が含まれていません。これを使用していた場合は、スクリプトエンジンモジュールに明示的に依存するように設定を移行し、それをモジュールパスに追加する必要があります。
js-scriptengine
モジュールを有効にするには、次のようにMaven依存関係として追加します。
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
<version>${graaljs.version}</version>
</dependency>
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>js</artifactId>
<version>${graaljs.version}</version>
<type>pom</type>
</dependency>
Mavenを使用していない場合は、--module-path=languages/js/graaljs-scriptengine.jar
のように、js-scriptengine.jarファイルをモジュールパスに手動で追加する必要があります。場合によっては、ScriptEngine
が見つかるように、コマンドラインに--add-modules org.graalvm.js.scriptengine
を追加する必要がある場合もあります。GraalJSScriptEngine
を直接使用する場合にのみ、org.graalvm.js.scriptengine
モジュールへの明示的な依存関係が必要です(下記参照)。最後に、jlink
を使用して、GraalJSのScriptEngine
を含むカスタムJavaランタイムイメージを生成することもできます。
例となるpom.xmlファイルは、GitHubのGraalJSリポジトリにあります。
推奨される使用方法 #
JavaScriptソースの不要な再コンパイルを避けるために、ScriptEngine.eval
ではなくCompiledScript.eval
を使用することをお勧めします。これにより、対応するCompiledScript
オブジェクトがアクティブである限り、JITコンパイルされたコードがガベージコレクションされるのを防ぎます。
シングルスレッドの例
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
CompiledScript script = ((Compilable) engine).compile("console.log('hello world');");
script.eval();
マルチスレッドの例
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
CompiledScript script = ((Compilable) engine).compile("console.log('start');var start = Date.now(); while (Date.now()-start < 2000);console.log('end');");
new Thread(new Runnable() {
@Override
public void run() {
try {
// Create ScriptEngine for this thread (with a shared polyglot Engine)
ScriptEngine engine = manager.getEngineByName("js");
script.eval(engine.getContext());
} catch (ScriptException scriptException) {
scriptException.printStackTrace();
}
}
}).start();
script.eval();
Bindings
によるオプションの設定 #
ScriptEngine
インターフェースは、オプションを設定するためのデフォルトの方法を提供しません。回避策として、GraalJSScriptEngine
はBindings
を介していくつかのContext
オプションの設定をサポートします。これらのオプションは次のとおりです。
polyglot.js.allowHostAccess <boolean>
polyglot.js.allowNativeAccess <boolean>
polyglot.js.allowCreateThread <boolean>
polyglot.js.allowIO <boolean>
polyglot.js.allowHostClassLookup <booleanまたはPredicate<String>>
polyglot.js.allowHostClassLoading <boolean>
polyglot.js.allowAllAccess <boolean>
polyglot.js.nashorn-compat <boolean>
polyglot.js.ecmascript-version <String>
これらのオプションは、評価されたJavaScriptコードに適用されるサンドボックス化ルールを制御し、アプリケーションがNashorn互換モード(--js.nashorn-compat=true
)で開始されていない限り、デフォルトでfalse
に設定されます。
ScriptEngine
を使用すると、実験的なオプションが許可されることに注意してください。これは、Bindings
を介して渡すことができる許可されたオプションの網羅的なリストです。GraalJSに追加のオプションを渡す必要がある場合は、以下に示すようにContext
を手動で作成する必要があります。
Bindings
を介してオプションを設定するには、エンジンのスクリプトコンテキストが初期化される前に、Bindings.put(<option name>, true)
を使用します。Bindings#get(String)
への呼び出しでもコンテキストの初期化につながる可能性があることに注意してください。次のコードは、Bindings
を介してpolyglot.js.allowHostAccess
を有効にする方法を示しています。
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
bindings.put("polyglot.js.allowHostAccess", true);
bindings.put("polyglot.js.allowHostClassLookup", (Predicate<String>) s -> true);
bindings.put("javaObj", new Object());
engine.eval("(javaObj instanceof Java.type('java.lang.Object'));"); // it will not work without allowHostAccess and allowHostClassLookup
この例は、たとえばbindings.put("polyglot.js.allowHostAccess", true);
を呼び出す前に、ユーザーがengine.eval("var x = 1;")
を呼び出すと機能しません。これは、eval
への呼び出しによってコンテキストの初期化が強制されるためです。
システムプロパティによるオプションの設定 #
JavaScriptエンジンへのオプションは、polyglot.
をプレフィックスとして付けることで、JVMの開始前にシステムプロパティを介して設定できます。
java -Dpolyglot.js.ecmascript-version=2022 MyApplication
または、ScriptEngine
を作成する前に、Javaアプリケーション内からプログラムでJavaScriptエンジンへのオプションを設定できます。ただし、これは、例で示されているBindings
を介して設定できるオプションではなく、JavaScriptエンジンに渡されるオプション(js.ecmascript-version
など)にのみ機能します。もう1つの注意点として、これらのシステムプロパティは、同時に実行されるすべてのScriptEngine
で共有されることです。
より柔軟性のあるContext
の手動作成 #
Context
オプションは、Context.Builder
のインスタンスを介して、GraalJSScriptEngine
に直接渡すこともできます。
ScriptEngine engine = GraalJSScriptEngine.create(null,
Context.newBuilder("js")
.allowHostAccess(HostAccess.ALL)
.allowHostClassLookup(s -> true)
.option("js.ecmascript-version", "2022"));
engine.put("javaObj", new Object());
engine.eval("(javaObj instanceof Java.type('java.lang.Object'));");
これにより、GraalJSで使用可能なすべてのオプションを設定できます。ただし、GraalJSScriptEngine
やContext
クラスなど、GraalJSへのハード依存が発生します。
サポートされているファイル拡張子 #
javax.script.ScriptEngine
のGraalJS実装は、JavaScriptソースファイルにはjsファイル拡張子、ESモジュールにはmjs拡張子をサポートしています。