RPG から Java を呼び出したときのコーディング・エラー

RPG プロトタイプでのメソッド・パラメーターの不正確な指定

Java メソッドのプロトタイプをコード化する際、戻り値およびパラメーターのタイプを正確に指定しないと、RPG コンパイラーは、メソッド・シグニチャーを不正確にビルドします。 プログラムが実行されると、間違ったメソッドが呼び出されるか、呼び出しが NoSuchMethodError Java 例外で失敗します。

呼び出しが NoSuchMethodError Java 例外で失敗する場合、RPG エラー・メッセージは、メソッドの呼び出しで使用された署名を示します。 以下の表は、Java タイプとメソッド・シグニチャー値の間のマッピングを示します。 Java タイプと RPG タイプ間のマッピングについては、表 30を参照してください。

Java タイプ 署名
boolean Z
byte B
char C
short S
int I
long J
float F
double D
any object Lclass;
any array [type

Java クラスのメソッド用の有効な署名のリストを表示するには、QSH コマンドを使用します。

 javap -s classname 

ここで、classname はパッケージと共に指定されます。例: java.lang.String クラスが標準の classpath にない場合は、javap に classpath オプションを指定できます。

javap -s classname -classpath classlocation

メソッド用の有効な署名をメソッド呼び出し用の RPG で使用される署名を比べ、マッピング・テーブルから作業することによって、プロトタイプのエラーを判別できます。

Java リソースの解放エラー

コンストラクターを呼び出すことで、 またはオブジェクトを戻すメソッドを呼び出すことで、 Java オブジェクトを作成した場合、 作成したオブジェクトは解放しない限り存在し続けます。 オブジェクトが解放されるのは次の場合です。

  1. RPG プログラムが、オブジェクトを解放する JNI 関数を呼び出したとき (Java を使用するためのその他の RPG コーディングを参照)。
  2. Java から固有メソッドへの呼び出し中にオブジェクトが作成された場合に固有メソッドが返されたとき。
  3. JVM が終了したとき。

Java メソッドを呼び出す RPG プロシージャーが RPG 固有のメソッドではない場合、 および RPG プロシージャーが、自分が作成したオブジェクトの解放に責任を持たない場合、 そのジョブは結果的にそれ以上オブジェクトを作成できなくなる可能性があります。

次のようなコード・フラグメントがあるとします。

       strObject = newString ('abcde');
       strObject = trim (strObject);
       data = getBytes (strObject);
       freeLocalRef (strObject);

このコードはオブジェクトの解放を引き受けているようですが、 実際にはこのコードは 2 つのオブジェクトを作成します。 1 つ目のオブジェクトは newString() 呼び出しによって作成され、 2 つ目のオブジェクトは trim() 呼び出しによって作成されます。 このコード・フラグメントを訂正するには、以下の 2 つの方法があります。

  1. 複数のオブジェクトを同時に解放:
           beginObjGroup();        
           strObject = newString ('abcde');
           strObject = trim (strObject);
           data = getBytes (strObject);
           endObjGroup();     		 
  2. 使用されているオブジェクトすべてを追跡し、それらを個別に解放:
           strObject = newString ('abcde');
           trimmedStrObject = trim (strObject);
           data = getBytes (trimmedStrObject);
           freeLocalRef (strObject);
           freeLocalRef (trimmedStrObject);
    

Java メソッドをほかの Java メソッドのパラメーターとして呼び出すと、 別の問題が起こることがあります。 次の例では、String パラメーターを取るコンストラクターから BigDecimal オブジェクトを作成しています。

       bigDec = newBigDecimal (newString ('12.345'));
          ...
       freeLocalRef (bigDec);

このコードの問題は、パラメーターの指定により String オブジェクトが作成されたのに、 RPG プロシージャーはこのオブジェクトを解放できないことです。 この問題を訂正するには、Java を呼び出す RPG コードの前に beginObjGroup() を呼び出し、 後で endObjGroup() を呼び出すか、以下のようにコーディングします。

       tempObj = newString ('12.2345');
       bigDec = newBigDecimal (tempObj);
       freeLocalRef (tempObj);
          ...
       freeLocalRef (bigDec);

存在しないオブジェクトの使用

固有のメソッドに静的な Object 変数 (定義に STATIC キーワード) がある場合、 または固有のメソッドが静的なグローバル Object 変数 (メイン・ソース・セクションで宣言した変数) を使用している場合、 その Object 変数は、その固有のメソッドが次に呼び出されるまで値を保持し続けます。 しかし、デフォルトでは、Java は固有メソッドの呼び出し時に作成されたオブジェクトをすべて解放します (Java がオブジェクトを解放しないようにする方法については、 Java を使用するためのその他の RPG コーディングを参照してください)。

RPG の "Object" は実際には数値オブジェクト参照です。 Java オブジェクトが解放されても、この数値オブジェクト参照を再利用することができます。 RPG 固有のメソッドが、明示的に解放の禁止が指定されていない静的な Object 変数を参照すると、 次のいずれかが発生する可能性があります。

  1. 数値オブジェクト参照が再使用されていない場合、 オブジェクト参照は無効となる可能性があります。
  2. オブジェクト参照は再使用されている可能性がありますが、 参照しているのは別のオブジェクトであるため、 RPG 固有のメソッドでそのオブジェクトを使用しようとしても、 エラーが発生する可能性があります。

オブジェクトの不正な再使用問題を防ぐには、次のようにします。