Java 8でJavaScript。スクリプトエンジンでNashornを試す

やや気が早いですが、Java 8のEarly Access版でお試し。
Nashornネタあまり出てこなそうなのでとりあえずスクリプトエンジンの復習です。


スクリプトエンジンはJava 6で導入された機能で、JavaVM上でJavaScriptRuby等のスクリプト言語が実行出来ます。特にJavaScriptJDKの中に実行エンジンが含まれているため、追加のライブラリ不要で使えるのがポイントです。Java 7でインボークダイナミックという機能が導入されJavaの中でスクリプトがより効率よく実行出来るようになりました。そして、Java 8でそのJavaScriptの実装がRhinoからインボークダイナミックを使ったNashornに置き換わります。つまり、よりJavaの中でJavaScriptが効率的に実行出来るようになるという事です。


では、とりあえずmainメソッドにソース書いてみます。

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
engine.eval("print(1+2);");


実行してみましょう。

3


わずか3行でJavaJavaScriptが動きますね。
うーんやっぱりJavaJavaScriptが動くのは不思議な感じ。
ちなみにengineのクラス名をSystem.outで出力してみると。

jdk.nashorn.api.scripting.NashornScriptEngine@6279cee3


確かにNashornになってます。


JavaからJavaScriptのfunctionを呼び出したい場合はScriptEngineクラスをInvocableにキャストすると呼び出せます。JavaScriptの「hoge」ファンクションをJavaから呼び出してみましょう。

engine.eval("function hoge(a,b){return a+b;}");
Invocable invocable = (Invocable) engine;
Object object = invocable.invokeFunction("hoge", 1, 2);
System.out.println(object); //3


キャストというのが少し微妙ですが、JavaからJavaScriptのfunctionが呼び出せて、JavaScriptからの戻り値もJavaで受け取る事ができます。


また、JavaScript内でJavaのクラスも扱えます。JavaScript内でLocalDateクラスを呼び出してみます。

engine.eval("print(Java.type('java.time.LocalDate').now());"); //2014-03-07


上記を実行すると今日の日付が出力されます。RhinoでimportPackage(またはimportClass)ファンクションを使用していましたが、Nashornは使用出来なくなっているので注意が必要です。どうしても互換性の為に使用する必要がある場合は、互換性スクリプトを事前に読み込む事で対応できます。

engine.eval("load('nashorn:mozilla_compat.js');importPackage(java.time);print(LocalDate.now());"); //2014-03-07


スクリプトエンジンはJavaの内部で簡易に記述出来るスクリプトが利用出来るほか、スクリプトで作成されたライブラリ資産がJavaで利用出来るようになるため、使い方によってはとても面白い事が出来ると思います。