目的
- 【追記】Java 8 で追加された以下の機能ですが、Java 11 で廃止されました。
- Java6 あたりから、Java内にJavaScriptエンジン(Rhino)が追加されています。
- Java8 ではJavaScriptエンジン(Nashorn)の性能が向上したという話なので、いまさらながら少し動かしてみました
- でも性能測定とかはしません
- メソッドの詳細な説明もしないです
概要
Java での JavaScript サポートは、ライブラリから扱える javax.script
パッケージと、そのコマンドライン版があります。
実際には JavaScript 以外のスクリプト言語も対応が予定されているみたいですが、現時点では JavaScript のみが対応されているみたいです。
コマンドライン版
コマンドライン版は、Java6, Java7 では JDKの bin ディレクトリに jrunscript
というコマンドがありました。これは Java8 でも残っているみたいです。
Java8 からは追加で JRE の bin ディレクトリに jjs
というコマンドがあります。
開発環境(JDK)ではなく利用環境(JRE)だけでも使えるようになったのかな。
今回は触っていません。
javax.script パッケージ
JavaScript のソースの文字列から実行することができます(ファイルから読み込んで実行も可能)。
また、Java と JavaScript でデータのやり取りやメソッドの呼び出しなども可能です。
サンプルソース
とりあえず動かしてみました。例外処理は手を抜いています。
package test.javascript;
import java.util.Date;
import java.util.List;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
/** Java と JavaScript の連携 */
public class JavaScriptTest {
public static void main(String[] args) throws Exception {
System.out.println("java.version: " + System.getProperty("java.version"));
// 対応している ScriptEngine の情報を出力
ScriptEngineManager manager = new ScriptEngineManager();
List<ScriptEngineFactory> engineFactories = manager.getEngineFactories();
for (ScriptEngineFactory factory : engineFactories) {
System.out.println("Engine: " + factory.getEngineName()
+ ", Version: " + factory.getEngineVersion());
System.out.println("Language: " + factory.getLanguageName()
+ ", Version: " + factory.getLanguageVersion());
System.out.println("Extensions: " + factory.getExtensions());
System.out.println("MimeTypes: " + factory.getMimeTypes());
System.out.println("Names: " + factory.getNames());
System.out.println();
}
ScriptEngine engine = manager.getEngineByName("JavaScript");
// JavaScript の実行
engine.eval("var message = 'Hello, I am JavaScript.'");
engine.eval("print('#1: ' + message)");
// Java のオブジェクトを JavaScript に渡してみる
engine.put("message2", "Hello, I am Java8.");
engine.put("today", new Date());
engine.eval("print('#2: ' + message2 + ' now : ' + today.toString())");
// JavaScript から Java のメソッドを使用
engine.eval("var obj = Java.type('test.javascript.JavaScriptTest');"
+ "print('#3: ' + obj.getMessage());");
engine.eval("obj.printMessage('Good afternoon.');");
// Java から JavaScript の値を取得
engine.eval("var message3 = 'Good evening.';");
Object message3 = engine.get("message3");
System.out.println("#5: " + message3);
// Java から JavaScript の関数を呼び出し
if (engine instanceof Invocable) {
Invocable invocable = (Invocable) engine;
engine.eval("var func = function(arg) { print('#6: ' + arg);}");
invocable.invokeFunction("func", "Good night.");
}
}
/** メッセージを返す */
public static String getMessage() {
return "Good morning.";
}
/** メッセージを出力 */
public static void printMessage(String message) {
System.out.println("#4: " + message);
}
}
動作結果はこんな感じ。
java.version: 1.8.0_65
Engine: Oracle Nashorn, Version: 1.8.0_65
Language: ECMAScript, Version: ECMA - 262 Edition 5.1
Extensions: [js]
MimeTypes: [application/javascript, application/ecmascript, text/javascript, text/ecmascript]
Names: [nashorn, Nashorn, js, JS, JavaScript, javascript, ECMAScript, ecmascript]
#1: Hello, I am JavaScript.
#2: Hello, I am Java8. now : Thu Nov 05 22:51:09 JST 2015
#3: Good morning.
#4: Good afternoon.
#5: Good evening.
#6: Good night.
落書き
- Rhino の読みは「ライノー」で、英語で犀のこと
- Nashorn のよみは「ナースホルン」でドイツ語で犀のこと
- ネタ元はオライリーのJavaScript本なんでしょうね