Java11 で Nashorn が 非推奨になったので Graaljs を試してみた

こんにちは、開発担当の Masa です。

Java11 がリリースされました。
現行版の帳票クリエータ for Java では JavaScript エンジンが必須なので、Nashorn が非推奨となったのは大問題です。

基本的には Rhino 推しなのですが、念のため Nashorn 互換モードがある Graaljs を試してみました。

まずは必要な jar をビルドします(Windows では無理です)。
基本的には以下のサイトの通りに実行すればビルド出来ます。
https://github.com/graalvm/graaljs/blob/master/docs/Building.md

筆者は Ubuntu 18.04.1 を最小インストールした直後の PC でビルドしたため、上記サイトの、Python、JDK8以降、git に加え以下のパッケージが不足していました。

make
ruby
gcc
g++

Windows PC 上の Eclipse で動作させるため、JavaScript エンジンとして動作させるのに必要な jar をかき集めます。
ビルドされた jar は各階層の mxbuild に格納されています。

必要最小限の jar は以下の場所に格納されているはずです。

graalvm/graaljs/graal-js/mxbuild/dists/graaljs.jar
graalvm/graaljs/graal-js/mxbuild/dists/graaljs-scriptengine.jar
graalvm/graal/sdk/mxbuild/dists/graal-sdk.jar
graalvm/graal/truffle/mxbuild/dists/truffle-api.jar
graalvm/graal/regex/mxbuild/dists/tregex.jar

実行出来るかどうかを軽く確認します。

public static void main(String[] args) {
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("graal.js");
    try {
        System.out.println(engine.eval("var hoge = 'test'; hoge;"));
    } catch (ScriptException e) {
	e.printStackTrace();
    }
}

================================================================================
output:test

動きました。

尚、Graaljs は Nashorn と同様に JavaImporter を使用する場合 "nashorn:mozilla_compat.js" のロードと、"-Dpolyglot.js.nashorn-compat=true" オプションの指定が必要になります。

JavaImporter は必要なので指定します。
"polyglot.js.nashorn-compat" オプションは "nashorn:mozilla_compat.js" のロードより先に実行する必要があります。
VM オプションで指定すると全体に影響が出るので、クラスがロードされた場合のみ設定されるようにシステムプロパティで設定します。

public static void main(String[] args) {
    // nashorn:mozilla_compat.js をロード可能にする
    System.setProperty("polyglot.js.nashorn-compat", "true");
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("graal.js");
    try {
        // JavaImporter を使用可能にする
        engine.eval("load('nashorn:mozilla_compat.js')");
        // 試しにインポートしてみる
        engine.eval("importPackage(Packages.com.oracle.truffle.js.scriptengine);");

        System.out.println(engine.eval("var hoge = 'test'; hoge;"));
    } catch (ScriptException e) {
	e.printStackTrace();
    }
}

====================================================================================
output:test

正常に動作することが確認出来たので、帳票クリエータを少しいじっていよいよ Graaljs で実行させます。

...実行させたのですが、結果は ReferenceError

Nashorn もそうだったのですが、グローバル変数をエンジン間で共有することが出来ないため帳票クリエータではエラーになります。
Nashorn では "--global-per-engine" オプションを指定した上で、グローバルスコープのコンテキストを使いまわすことで回避出来ましたが、Graaljs にはこのオプションを指定出来ません。

結果

Graaljs スクリプトエンジンは帳票クリエータでは使用できません。

https://github.com/graalvm/graaljs/issues/47
この問題は既に報告されていますが、どういった対応が行われるのか待ちたいと思います。