Java メソッドの ILE RPG からの呼び出し

この節では、Java(TM) メソッドを ILE RPG プログラムから呼び出す方法について説明します。

メソッドが静的メソッドでない場合、これを「インスタンス・メソッド」と呼びます。 そのメソッドを呼び出すための特別な最初のパラメーターとして、オブジェクト・インスタンスがコーディングされなければなりません。 例えば、インスタンス・メソッドが 1 つのパラメーターを伴ってプロトタイプされている場合であれば、ユーザーは 2 つのパラメーターを指定して呼び出さなければならず、その最初がインスタンス・パラメーターになるようにする必要があります。

以下のステップでは、ILE RPG から Java メソッドへの呼び出しについて説明します。

  1. Java メソッドは、既存の命令コード CALLP (戻り値がないと予想される場合) および EVAL (戻り値があると予想される場合) を使用して呼び出すことができます。ユーザーの RPG プロシージャーが Java メソッドを呼び出そうとすると、RPG はその Java 仮想マシン (JVM) が開始済みであるかどうかをチェックします。まだ開始されていない場合は、RPG はユーザーに代わって JVM を開始します。Java 仮想マシン (JVM) の作成で説明されている JNI 機能を使用して、ユーザー自身が JVM を開始することもできます。
  2. ユーザーが自分のクラス (あるいは通常の java.xxx クラス以外のすべてのクラス) を使用している場合は、Java メソッドを呼び出す前にユーザーの CLASSPATH 環境変数を必ずセットアップしておいてください。RPG がユーザーに代わって JVM を呼び出す時、RPG はユーザーの CLASSPATH 環境変数の中にあるクラスを標準クラスパスへ追加します。 これによって、ユーザーが自分のクラスを使う時に Java はそれらのクラスを見つけることができます。CLASSPATH 環境変数を対話式に設定するには、次のようにします。
    ===>ADDENVVAR ENVVAR(CLASSPATH)
                  VALUE('/myclasses/:/xyzJava/classes/')
    ディレクトリーはコロンで分ける必要があります。
  3. 通常、Java は自分自身のガーベッジ・コレクションを行ない、オブジェクトがいつ不要になるかを検出します。ユーザーが非ネイティブ RPG プロシージャーから Java コンストラクターを呼び出すことによってオブジェクトを作成する場合は、Java はそのオブジェクトを破棄してよいということを知る方法がないため、それらを 破棄しません。複数のオブジェクトの同時解放を Java に通知 で説明する JNI 機能を呼び出すことによって、 複数のオブジェクトに対するガーベッジ・コレクションを同時に使用可能にできます。 もうオブジェクトが不要であることをユーザーが 知っている場合は、一時オブジェクトの使用が終了したことを Java に伝えるで説明する JNI 機能を 呼び出すことによって、このことを Java に伝える必要があります。
注意:
Java はスレッドを使用するため、Java と相互作用するすべてのモジュールに THREAD(*SERIALIZE) キーワードをコーディングしておく必要があります。 RPG は明らかに自動ストレージのみを使用するサブプロシージャーにあっても、静的ストレージに強く依存します。 この静的ストレージを正しく取り扱うには THREAD(*SERIALIZE) が必要です。 これは Java メソッドへの呼び出しを含むモジュールのみではなく、Java との相互作用中に呼び出される可能性があるモジュールすべてに適用されます。

さまざまな JNI 機能の詳細については、Java を使用するためのその他の RPG コーディングを参照してください。

例 1

この例では、目的は 2 つの BigDecimal 値を一緒に加算することです。これを行なうため、2 つの BigDecimal オブジェクトは BigDecimal クラス用のコンストラクターを呼び出してインスタンス化される必要があり、フィールドは BigDecimal オブジェクトを保管できるように宣言される必要があり、さらに BigDecimal クラスにある add() メソッドが呼び出される必要があります。

図 77. BigDecimal Java クラスを呼び出す RPG コーディング例
 *   String パラメーターを受け取る BigDecimal コンストラクターのプロトタイプ。
 *   新しい BigDecimal オブジェクトを戻します。
 *   string パラメーターはこのコンストラクターによって変更されないため、
 *   CONST キーワードをコーディングすることになります。これによって
 *   コンストラクターの呼び出しがより便利になります。
 *
D bdcreate1       PR              O   EXTPROC(*JAVA:
D                                      'java.math.BigDecimal':
D                                      *CONSTRUCTOR)
D    str                          O   CLASS(*JAVA:'java.lang.String')
D                                     CONST
 *
 *   double パラメーターを受け取る BigDecimal コンストラクターのプロトタイプ。
 *   8F は Java の double データ・タイプにマップするため、
 *   VALUE で渡す必要があります。BigDecimal オブジェクトを戻します。
 *
D bdcreate2       PR              O   EXTPROC(*JAVA:
D                                      'java.math.BigDecimal':
D                                      *CONSTRUCTOR)
D   double                       8F   VALUE
 *   BigDecimal オブジェクトを保管するフィールドを定義します。
 *
D bdnum1          S               O    CLASS(*JAVA:'java.math.BigDecimal')
D bdnum2          S               O    CLASS(*JAVA:'java.math.BigDecimal')
 *
 *   使用しているコンストラクターのいずれかが、String オブジェクトを
 *   必要としているため、これらのコンストラクターのいずれかを作成する必要が
 *   あります。byte 配列をパラメーターとして受け取る String コンストラクターを
 *   プロトタイプします。これは String オブジェクトを戻します。
 *
D makestring      PR              O    EXTPROC(*JAVA:
D                                       'java.lang.String':
D                                       *CONSTRUCTOR)
D    bytes                      30A    CONST VARYING

 *
 *  String オブジェクトを保管するフィールドを定義します。
 *
D string          S               O    CLASS(*JAVA:'java.lang.String')

 *
 *  BigDecimal 追加メソッドのプロトタイプ。BigDecimal オブジェクトをパラメーター
 *  として受け取り、BigDecimal オブジェクトを戻します (パラメーターおよび
 *  BigDecimal オブジェクトの合計が、この呼び出しを行なうために使用されます)。
 *
D add             PR              O    EXTPROC(*JAVA:
D                                       'java.math.BigDecimal':
D                                       'add')
D
CLASS(*JAVA:'java.math.BigDecimal')
D   bd1                           O
CLASS(*JAVA:'java.math.BigDecimal')
D                                      CONST

 *
 *  合計を保管するフィールドを定義します。
 *
D sum             S               O
CLASS(*JAVA:'java.math.BigDecimal')
D
D double          S              8F    INZ(1.1)
D fld1            S             10A
 * Define a prototype to retrieve the String version of the BigDecimal 
D getBdString     PR              O    CLASS(*JAVA:'java.lang.String')
D                                      EXTPROC(*JAVA:
D                                       'java.lang.BigDecimal':
D                                       'toString')
 * Define a prototype to retrieve the value of a String
D getBytes        PR         65535A    VARYING
D                                      EXTPROC(*JAVA:
D                                       'java.lang.String':
D                                       'getBytes')
 * Define a variable to hold the value of a BigDecimal object
D bdVal           S             63P 5

呼び出しを行なうコードは次の通りです。

図 78.
 *  fld1 から String オブジェクトを作成するために、String クラスのコンストラクターを
 *  呼び出します。コンストラクターを呼び出しているため、
 *  最初のパラメーターとして String オブジェクトを渡す必要はありません。
 *
C                   EVAL      string = makestring('123456789012345678901234567890')
 *
 *  インスタンス化したばかりの String オブジェクトを使用して、String パラメーターを
 *  受け取る BigDecimal コンストラクターを呼び出します。
 *
C                   EVAL      bdnum1 = bdcreate1(string)

 *
 *  double をパラメーターをして受け取る BigDecimal コンストラクターを
 *  呼び出します。
 *
C                   EVAL      bdnum2 = bdcreate2(double)


 *
 *  add メソッドを呼び出すことにより、2 つの BigDecimal オブジェクトを
 *  一緒に加算します。プロトタイプは、add が 1 つのパラメーターを
 *  受け取ることを示していますが、add は静的メソッドではないため、
 *  呼び出しを行なうために BigDecimal オブジェクトも渡す必要があり、
 *  かつそれは最初のパラメーターであることが必要です。
 *  bdnum1 は呼び出しを行なうために使用するオブジェクトで、
 *  bdnum2 はパラメーターです。
 *
C                   EVAL      sum = add(bdnum1:bdnum2)

 *  ここで sum には bdnum1 + bdnum2 の値を持つ BigDecimal
 *  オブジェクトが入ります。
C                   EVAL      bdVal = %DECH(getBdString(sum) : 63 : 5)
 * val には sum の値が入ります。
 * sum の値が、変数 "val" が持つことができる数より大きい場合、
 * オーバーフロー例外が発生します。

例 2

この例は、ILE RPG %TRIM 組み込み関数の代わりに trim() メソッドを使用して Java で TRIM を行なう方法について示します。String クラスにある trim() メソッドは静的メソッドではないため、これを呼び出すには String オブジェクトが必要です。

図 79. trim() Java メソッドを使用する RPG コーディング例
 *  トリムしたい String オブジェクトを保管するフィールドを定義します。
 *
D str             S               O
CLASS(*JAVA:'java.lang.String')

 *
 *  String クラス用のコンストラクターのプロトタイプ。
 *  コンストラクターは byte 配列を想定しています。
 *
D makestring      PR              O   EXTPROC(*JAVA:
D                                      'java.lang.String':
D                                      *CONSTRUCTOR)
D                                     CLASS(*JAVA:'java.lang.String')
D   parm                        10A

 *
 *  String を byte 配列に変換する String メソッド getBytes のプロトタイプ。
 *  変換後はこの byte 配列を alpha フィールドに保管します。
 *
D getBytes        PR            10A   EXTPROC(*JAVA:
D                                       'java.lang.String':
D                                       'getBytes') VARYING

 *
 *  String メソッド trim のプロトタイプ。これはパラメーターは取りませんが、
 *  静的メソッドではないため、String オブジェクトを使用して
 *  呼び出す必要があります。
 *
D trimstring      PR              O   EXTPROC(*JAVA:
D                                      'java.lang.String':
D                                      'trim')
D fld             S             10A     INZ('   hello    ') VARYING

この呼び出しは次のようにコーディングされます。

図 80. String コンストラクターに対する RPG 呼び出し
 * String コンストラクターを呼び出します。
 *
C                   EVAL      str = makestring(fld)

 *
 * String trim() メソッドを呼び出すことにより、ストリングをトリムします。
 * この str フィールドを、結果を保管するために再利用します。
 *
C                   EVAL      str = trimstring(str)

 * 
 * ストリングをバイト配列に変換して戻し、
 * これを fld に保管します。
 *
C                   EVAL      fld = getBytes(str)

呼び出しを行なうのにオブジェクトが必要でない場合を除き、静的メソッドは同じ方法で呼び出されます。 上記の getBytes() メソッドが静的メソッドである場合は、呼び出しは次の例のようになります。

C                        EVAL      fld = getBytes()

メソッドが値を戻さない場合は、CALLP 命令コードを使用します。

オブジェクトの作成

非静的メソッドを呼び出すには、オブジェクトが必要です。オブジェクトのクラスは、メソッドを含んでいるクラスと同じでなければなりません。 使用可能なオブジェクトが既にあっても、新たなオブジェクトをインスタンス化する必要がある場合があります。 これはクラス・コンストラクターを使用して行ないます。クラス・コンストラクターは静的メソッドでもインスタンス・メソッドでもありません。 したがってクラス・コンストラクターにはインスタンス・パラメーターは必要ありません。特別なメソッド名である *CONSTRUCTOR が、コンストラクターのプロトタイピングを行なう時に使用されます。

例えば、クラス BigDecimal には float パラメーターを受け取るコンストラクターがあります。

このコンストラクターは次のようにプロトタイプされます。

D bdcreate        PR              O   EXTPROC(*JAVA:
D                                       'java.math.BigDecimal':
D                                       *CONSTRUCTOR)
D    dnum                        4F   VALUE

パラメーターは Java float データ・タイプにマップされるため、値による受け渡しをする必要があることに注意してください。

このコンストラクターは次のように呼び出します。

D bd              S               O   CLASS(*JAVA:
D                                           'java.math.BigDecimal')
  /free
    bd = bdcreate(5.2E9);
  /end-free

戻されるオブジェクトのクラスはコンストラクター自身のクラスと同じであるため、 CLASS キーワードはコンストラクターの場合には冗長になりますが、コーディングしてもかまいません。