【コラム】

Java API、使ってますか?

34 スクリプト言語とJavaを結びつけるJSR 223

    杉山貴章  [2007/12/10]

    JSR 223: Scripting for the Java Platform

    現在、Javaプラットフォームではスクリプト言語のサポートが急速に進められている。同時に、Java VM上で動作するさまざまなスクリプト言語の実装が登場しており、JavaプラットフォームはすでにJava言語という枠を飛び越え、マルチ言語環境に進化しようとしている。本連載第31回で紹介したBeanShellも、Javaベースのスクリプト言語のひとつだ。

    今回取り上げるのは、そのようなさまざまなスクリプト言語とJavaを結びつける役割を果たす「JSR 223: Scripting for the Java Platform」だ。ご存知のように同APIはJava SE 6よりJavaの標準クラスライブラリとして統合されている。JSR 223ではJavaプログラム内で各種スクリプトを実行する、およびスクリプト側からJavaプログラムにアクセスするための標準的な方法が提供される。

    JDK 6にはJavaで実装されたJavaScriptエンジンであるRhinoがバンドルされており、標準で利用できるようになっている。その他のスクリプト言語についても対応が進められていて、scripting.dev.java.netで公開されている最新の参照実装には各種エンジンが搭載されている。

    最新の参照実装でいろいろなスクリプトを実行する

    まず、JDK 6でJavaScriptを利用する方法をおさらいしておこう。スクリプトの実行にはjavax.script.ScriptEngineクラスを利用する。まずファクトリクラスであるjavax.script.ScriptEngineManagerのインスタンスを生成し、そこからScriptEngineを取得してeval()メソッドでスクリプトを実行すればよい。具体的にはリスト1のようになる。

    リスト1 ScriptingForJavaScript.java - JavaプログラムでJavaScriptを実行

    package apisample;
    
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    
    public class ScriptingForJavaScript {
        public static void main(String[] args) throws Exception {
            ScriptEngineManager factory = new ScriptEngineManager();
            ScriptEngine engine = factory.getEngineByName("js");
    
            try {
                engine.eval("print(\"Hello, JavaScript!\")");
            } catch (ScriptException ex) {
                ex.printStackTrace();
            }
        }
    }
    

    JavaScriptは標準でサポートされているので、ScriptingForJavaScript.javaは通常通りコンパイル/実行できる。

    さて、JavaScript以外のスクリプト言語を利用するには別途JSR 223の参照実装を入手しなければならない。最新の実装は前述のプロジェクトサイトにあるドキュメント&ファイルセクションからダウンロードできる。jsr223-engines.zipまたは jsr223-engines.tar.gzを任意の場所 (ここでは[JSR223-ENGINES]と記載する) に解凍して使用する。

    配布ファイルにはサポートされるスクリプトエンジン用のフォルダが含まれており、各フォルダ毎に以下の3つのフォルダが用意されている。

    • bin - コマンドライン環境実行用のシェルスクリプトまたはbatファイルを格納
    • build - JSR 223対応のエンジンを格納
    • lib - 各スクリプトの実装を格納

    そのうちbinとbuildについてはすでに用意されているが、libに格納する実装だけはそれぞれのプロジェクトサイトから別途ダウンロードしてこなければならない。必要とするバージョンについてはREADME.TXTに記載されている。

    ここではBeanShellを使用してみる。BeanShellの場合はバージョン2.0 Beta5が必要と書かれているが、BeanShellの公式サイトで配布されている最新版は2.0 Beta4なのでこれを使う。このページよりbsh-2.0b4.jarをダウンロードし、[JSR223-ENGINES]\beanshell\libに配置する。

    このbsh-2.0b4.jarとbuildフォルダのbsh-engine.jarをクラスパスに含めることで、JavaプログラムからBeanShellを利用できるようになる。ためしにJDK 6付属のjrunscriptコマンドを使ってみよう。jrunscriptコマンドはqオプションで利用可能なスクリプト言語を調べることができ、lオプションでコマンドラインモードでスクリプトを実行できる(プロンプト1)。

    プロンプト1 jrunscriptコマンドでBeanShellを利用する

    > jrunscript -cp [JSR223-ENGINES]/build/bsh-engine.jar;[JSR223-ENGINES]/lib/bsh-2.0b4.jar -q
    Language BeanShell 2.0b5 implemention "BeanShell Engine" 1.0
    Language ECMAScript 1.6 implemention "Mozilla Rhino" 1.6 release 2
    
    > jrunscript -cp [JSR223-ENGINES]/build/bsh-engine.jar;[JSR223-ENGINES]/lib/bsh-2.0b4.jar -l bsh
    beanshell>
    

    続いてJavaプログラムからBeanShellスクリプトを実行してみよう。手順はJavaScriptの場合とまったく同じで、リスト2のようにする。ここでは簡単なウィンドウを表示させるスクリプトを実行している(第31回参照)。

    リスト2 ScriptingForBeanShell.java- JavaプログラムからBeanShellスクリプトを実行

    package apisample;
    
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    
    public class ScriptingForBeanShell {
        public static void main(String[] args) throws Exception {
            ScriptEngineManager factory = new ScriptEngineManager();
            ScriptEngine engine = factory.getEngineByName("bsh");
    
            try {
                engine.eval(
                        "import javax.swing.*;" + 
                        "f = new JFrame(\"BeanShell Sample\");" + 
                        "f.getContentPane().setLayout(new FlowLayout());" + 
                        "button1 = new JButton(\"Hello\");" + 
                        "button2 = new JButton(\"BeanShell!\");" + 
                        "f.getContentPane().add(button1);" + 
                        "f.getContentPane().add(button2);" + 
                        "f.setSize(300, 200);" + 
                        "f.setVisible(true);"
                );
            } catch (ScriptException ex) {
                ex.printStackTrace();
            }
        }
    }
    

    コンパイルおよび実行は、スクリプトエンジンのJARファイルをクラスパスに含めてプロンプト2のように行う。実行するとBeanSehllスクリプトによって図1のようなウィンドウが表示されるはずだ。

    プロンプト2 リスト2を実行

    > javac -cp ./;[JSR223-ENGINES]/build/bsh-engine.jar;[JSR223-ENGINES]/lib/bsh-2.0b4.jar apisample\ScriptingForBeanShell.java
    > java -cp ./;[JSR223-ENGINES]/build/bsh-engine.jar;[JSR223-ENGINES]/lib/bsh-2.0b4.jar apisample.ScriptingForBeanShell
    

    図1 BeanShellスクリプトによって生成されたウィンドウ

    次に、Javaプログラムからスクリプトのメソッドをコールしてみよう。メソッドのコールには、スクリプトエンジン(ScriptEngine実装)がjavax.script.Invocableインタフェースをimplementsしている必要がある。しかしBeanShellのエンジンはこれをimplementsしていないので(TODOということになっている)、今回はInvocableをサポートしているGroovyを使って試してみることにする。

    README.TXTによればGroovyを使うには1.1-beta-2が必要とのことなので、公式サイトのリポジトリより「groovy-all-1.1-beta-2.jar」をダウンロードして[JSR223-ENGINES]\groovy\libに配置する。

    プログラムはリスト3のようになる。ここではGroovyスクリプトでadd()メソッドを定義し、それをJavaプログラムからInvocableのinvokeFunction()を利用して呼び出している。

    リスト3 ScriptingForGroovy.java - JavaプログラムからGroovyのメソッドを呼び出す

    package apisample;
    
    import javax.script.Invocable;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    
    public class ScriptingForGroovy {
        public static void main(String[] args) throws Exception {
            ScriptEngineManager factory = new ScriptEngineManager();
            ScriptEngine engine = factory.getEngineByName("groovy");
    
            String script = "def add(x, y) { x + y }";
            try {
                engine.eval(script);
                Invocable invocable = (Invocable)engine;
                Object[] params = { new Integer(50), new Integer(100) };
                Object result = invocable.invokeFunction("add", params);
                System.out.println(result);
            } catch (ScriptException ex) {
                ex.printStackTrace();
            }
        }
    
    }
    

    コンパイルおよび実行は、Groovyのスクリプトエンジンをクラスパスに含めてプロンプト3のように行う。

    プロンプト3 リスト3の実行

    > javac -cp ./;[JSR223-ENGINES]/build/groovy-engine.jar;[JSR223-ENGINES]/lib/groovy-all-1.1-beta-2.jar apisample\ScriptingForGroovy.java
    > java -cp ./;[JSR223-ENGINES]/build/groovy-engine.jar;[JSR223-ENGINES]/lib/groovy-all-1.1-beta-2.jar apisample.ScriptingForGroovy
    150
    

    JSR 223を使用すれば、JavaScriptだけでなくさまざまなスクリプト言語を共通の方法で利用できる。今回はBeanShellとGroovyを取り上げたが、ぜひ他のスクリプト言語も試してみてほしい。なお、Java SE 7ではJavaScriptに加えてBeanShellやGroovy、JRubyなどといったスクリプト言語の標準サポートが検討されている。

    提供:マイナビ

    会員登録はこちら

    大学・大学院・短大・専門学生向けの就職情報サイト「マイナビ2010」「マイナビ2009」に今すぐ登録しよう!  大手企業からベンチャー企業までの約13,000社の企業情報を公開、エントリーが可能です。2010年卒予定の方は「マイナビ2010」に、2009年卒予定の方は「マイナビ2009」に登録してください。

    毎日コミュニケーションズはプライバシーマークを取得しています。

    関連記事

    関連サイト

    新着記事

    特設サイトの情報

      人気記事

      一覧

        イチオシ記事

        新着記事

        特別企画

        マイナビニュースマガジン