Nashornのセッションに出だけど、色々分からないのでScript Engineのお勉強1
まえがき
JavaDayTokyo2014 一発目のセッションでは、今まで気になりつつも、触る事が出来ていない、
Nashorn(ナスホーン、ナショーン)のセッションを聴講してきました。
話を聞いてみて、面白いなと思ったものの、
これは実際使ってみないと実感が湧かない(特に実際使うという場面において)
と思いましたので、この記事はセッションのFBも踏まえつつ、「Nashorn試してみた」的なエントリーとの
ハイブリットな投稿になると思います。実際、セッションの冒頭でもNashorn使ってみた人?というアンケートがありましたが、
手を挙げていた人は1割にも満たなかったので、Java8の新機能としてfeatureされつつも、
なかなかまだ実際に使っている人は少ない、という所でしょうか。
自分もその中の一人なので、まずは「Script Engineって何? Nashornって何?」という所から初めていきます。
※ので、結果的にセッション内容のFBに本気記事ではほとんど触れません。
Nashornとは
- 新しいScript Engineです。
- Script Engineとは、いわゆるScript言語を実行するEngineです。つまり、JavaにおけるScript Engineは、
Javaからスクリプト言語を呼び出したり(あるいはその逆)の機能を提供するものになります。
- Nashornは、JavascriptのScript Engineなので、Java VMからJavaScriptを実行する機能を提供します。
- Nashornは、Nashorn jsr223 engine notesで策定されています。
ここで一つ注意しておくべきことは、スクリプトエンジン自体は、新しい機能では無いという点です。
Script Engine自体は上記のリンク先にあるように,Java6から提供されています。
なので、新しいScript Engineの一つとして、NashornがJava8から追加されたということですね。
まずはScriptEngine動かす(java8だとデフォルトでNashornを動かす)。
ということで、なんとなくNashorn及びScript Engineのイメージもついたところで、実際に関数を実行してみます。
これ自体はめちゃくちゃ簡単で、すぐに動かせました。
というか、動かし方事態は、Rhinoの時と基本的に全く同じなので、
ScriptEngineに関連する記事はすぐ見つけられました。
で、すぐHello worldが出せました。
使っているEngine名を確認するとNashornと出ているので、無事Nashornが使えていることも確認できます。
ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine engine = scriptEngineManager.getEngineByName("js"); System.out.println(engine.getFactory().getEngineName()); try { engine.eval("print('HelloWorld!')"); } catch (ScriptException e) { e.printStackTrace(); } //出力 Oracle Nashorn // Engineの名前はOracle Nashornってことなのかな HelloWorld! // printってのがとりあえず標準出力を出す為に提供されているらしい
よしよし。
ところで、
色んなサイトをみると、すぐみんなこのprintって関数使ってHelloWorldやってるんですが、
printって何?
ってなりませんでしたか?僕はなりましたw
で、中身出してみたら、また色々と・・・w
printの中身については別途記事で書きます。
ちなみにprintの中身は下です。
色々気になりますよね?w
function print() { var writer = context != null? context.writer : engine.context.writer; if (! (writer instanceof java.io.PrintWriter)) { writer = new java.io.PrintWriter(writer); } var buf = new java.lang.StringBuilder(); for (var i = 0; i < arguments.length; i++) { if (i != 0) { buf.append(' '); } buf.append(String(arguments[i])); } writer.println(buf.toString()); }
ともあれ、printという関数はScript Engineにおいて、標準出力として使用できるみたいいです。
もちろん、普通にJavaScriptを書いて動かせます。関数を動かすなど。
ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine engine = scriptEngineManager.getEngineByName("js"); try { engine.eval("function hello() {print('Hello World!')}"); Invocable invocable = (Invocable)engine; Object obj = invocable.invokeFunction("hello"); } catch (ScriptException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } 出力 : Hello World!
Invokeしてキャストしてるところがなぁ。。というのはありつつ。
IDEでこの関数を読み取ってくれるなら嬉しいですが、実行時エラーになってしまうのが嫌ではありますね。
引数入れて関数呼ぶのも出来ます。
そして、面白いと思ったのは、変数の引き渡しもできます。
引き渡し
Integer i = 241; engine.put("key",i); System.out.println(engine.eval("typeof(key);")); System.out.println(engine.eval("key")); 出力 : number 241
色々対応してるみたいで
js | java |
Number | Double,Integer,Long,.... |
String | String |
Boolean | Boolean |
未定義 | Singleton Object |
Object | Map |
↑こんな感じ
まずはJavaからJavascriptを呼び出すことにおいて、基本的なことは一通りできそうです。
色々やれること、勉強することがありそうです。まずはここまで。