BeanShell
BeanShellは、 Java VM上で動作するスクリプト言語です。
Groovy、Rhino(JavaScript)、Jython(Python)などの仲間ですが、特徴は

  • Javaの文法に非常によく似ている。 Groovy、JavaScriptもそれなりに似ていますが、それらよりも似ています。
  • JARファイルが非常に小さい(基本機能だけなら150KB以下)
  • JSR-274として標準化が企画されている。
といったところです。
JARファイルが10倍の1.5MB以上あるGroovyに比べると、当然できないことも多数あります。
その筆頭は、スクリプト内でクラスを定義できないことです。 クラスは全てJavaで記述し、正常にコンパイルできたものを、 まさにスクリプトのように順番にBeanShellで呼び出して実行するという考え方になります。
また、GroovyにはPerlやRubyなどから導入したとみられる、 キータイプ数を減らす各種の構文がありますが、 BeanShellにはPerlやRubyのフレーバーは全く感じられません。


ダウンロードとインストール
ダウンロードはこのページから。
一番上の「bsh-2.0b4.jar」(約280KB)には、それより下の全ての機能が入っています。
単純に、JavaVM上でスクリプトを解釈実行させたい場合に必須なのは「bsh-core」です。
「bsh-commands」は、BeanShellをコンソールシェルとして実行する際に便利なコマンドを定義した追加パッケージです。 マニュアルのサンプルなどにもよく登場する"print"もコマンドなので、 bsh-coreだけでbsh-commandsがなければprintは使えないので注意が必要です。
「bsh-classpath」は、addClassPathコマンドなどを使って、 スクリプト内で動的にCLASSPATHを変更する機能を提供します。
「bsh-bsf」は、BSF(Bean Scripting Framework)の統一APIを使って、 JavaVMからスクリプトを解釈実行する際に必要になります。
個人的には「bsh-2.0b4」(All)を使うと、自分が作っている「StringUtil」 とクラス名が衝突するので明示的にパッケージ修飾が必要という不便があるものの、 addClassPathコマンドが便利なのでAllを使うのがいいと思います。
それで、ダウンロードしたJARファイルは展開の必要は無く、 これがイコール言語処理系としてのJARです。(追加ドキュメントのよーなものはありません) そのままCLASSPATHに通して使うことができます。


スクリプトの実行
Windowsでは、次のようなバッチファイルを作って実行すると良いと思います。

@echo off
set CLASSPATH=D:\usr\java\lib\scripting\bsh-2.0b4.jar
java bsh.Interpreter %1 %2 %3 %4 %5 %6 %7 %8 %9

Linuxだとこんな感じでしょうか。

#! /bin/sh

export CLASSPATH=$HOME/java/lib/scripting/*
java bsh.Interpreter $@

なお、コマンドライン引数はBeanShellスクリプト中からは「bsh.args[0]」のようにして参照できます。


文法の特徴

  • Javaと同様に変数に型(クラスまたはプリミティブ型)を宣言できるが、型を宣言しない変数を利用できる。 型を宣言しない場合、以前と異なる型のオブジェクトなどを自由に代入できる。 型を宣言した場合、それ以外のオブジェクトなどを代入しようとするとエラーになる。
    varをつけて、型を強制しない変数を明示的に宣言することもできる。
  • Java Beanのsetter/getterをプロパティへの直接アクセスのように書ける。 例えば「a.setLabel("abc");」は「a.label = "abc";」と書ける。
  • HashtableなどのMapにアクセスする簡易文法がある。例えば、 「hash.put("key", "value");」は「hash{"key"} = "value";」と書ける。
  • switch文はintだけでなく、オブジェクトの値で分岐させることができる。
  • Java5と同様のboxing/unboxingができる。例えば、intとIntegerの間は明示的な型変換なしで代入ができる。
  • javax.swing.event, javax.swing, java.awt.event, java.awt, java.net, java.util, java.io, java.lang は最初からインポートされている。
  • メソッドの定義は、引数の型も戻り値の型も省略できる(return文はある)。
    他の言語での「function」「def」のような、メソッドを定義するためのキーワードは無い。
  • メソッド内からグローバルスコープの変数にアクセスするためのglobal、superキーワードや、 this.callerがある。


exec()コマンドの注意
BeanShellにはcd()、cp()など 組み込みコマンドが幾つかあって便利に使えます。
その中にexec()という子プロセスを実行できる物があってこれも便利ですが、一点注意が必要です。
標準出力または標準エラー出力に出力があるコマンドを実行した場合、応答が返ってこなくなる現象があります。
これはBeanShellの問題ではなく、JavaのProcessBuilderクラスで応答を処理しなかった場合に一般にみられる現象で、 回避するにはexec()の代わりにJavaのProcessBuilderを使って以下の例のように応答を処理する方法があります。

ProcessBuilder b = new ProcessBuilder(command);
b.redirectErrorStream(true);
Process p = b.start();
try (BufferedReader r = new BufferedReader(
        new InputStreamReader(p.getInputStream(), Charset.defaultCharset()))) {
    String line;
    while ((line = r.readLine()) != null) {
        //System.out.println("[" + line + "]");
        System.out.println(line);
    }
}
int status = p.waitFor();

Java kowaza Top

(first uploaded 2009/05/16 last updated 2025/01/25, URANO398)