| Java からの手続き型 COBOL の呼び出し | Java からのオブジェクト COBOL の呼び出し |
この章では、COBOL プログラムから Java オブジェクトにアクセスする方法について説明します。
Micro Focus Java サポートでは、オブジェクト COBOL プログラムやオブジェクト COBOL クラスから Java オブジェクトへメッセージを送ることができます。Java は、オブジェクト COBOL の Java ドメインを経由してサポートされます。Java ドメインでは、COBOL プログラム内で Java クラスを宣言することができます。これにより、Java クラスへメッセージを送信できます。また、Java クラスから COBOL へメッセージを送信することもできます。詳細は、『Java からのオブジェクト COBOL の呼び出し』 の章を参照してください。
Java ドメイン サポートは、図 3-1 に示すように、それぞれの Java オブジェクトに対して COBOL プロキシオブジェクトを作成することで実現されます。宣言するクラス自身は、Java クラスの静的メソッドに対するプロキシです。
COBOL ランタイム システムは、メッセージとともに送られるパラメータを COBOL データ型から Java データ型に変換します。メソッドがパラメータを戻す場合は、Java データ型から COBOL データ型へ変換されます。
この項では、 オブジェクト COBOL の Java ドメインを使用して Java メソッドを呼び出すための COBOL プログラムのコーディング方法を説明します。プログラムは、オブジェクト COBOL クラスとして書かれている必要はありませんが、Class-Control 節が含まれており、 Java メソッドを呼び出すたびに INVOKE 動詞が使用されなければなりません。
COBOL プログラムで使用する Java クラスは、それぞれ Class-Control 節で宣言されている必要があります。クラスが存在するパッケージは、パッケージの完全名の前に $java$ をつけて指定する必要があります。このプリフィクスは、COBOL ランタイム システムが Java ドメインからクラスをロードするように指示します。
たとえば次のとおりです。
class-control.
jRectangle is class "$java$java.awt.Rectangle"
.
この例では、java.awt パッケージ中の Rectangle クラス の COBOL プロキシオブジェクトとして jRectangle を宣言しています。このパッケージは、Java クラスパス上に存在している必要があります。存在していない場合は、プログラムが実行時に失敗します。
それぞれの Java クラスには、オブジェクトをインスタンス化するコンストラクタメソッドがあります。Java では、コンストラクタメソッドの名前はクラスの名前と同じです。COBOL からこれらのメソッドを呼び出せるように、これらのメソッドは COBOL プロキシオブジェクトの new メソッド名にマップされます。
Java クラスのさまざまなコンストラクタは、それぞれ異なる数と組み合わせのパラメータを使用して、作成中のインスタンスをインスタンス化します。たとえば、Java Rectangle クラスは、次に示す 2 つの Java コード例を始めとして、さまざまな方法でインスタンス化することができます。
Rectangle r1 = new Rectangle () // 長方形 (x,y) = 0,0, 幅=0, 高さ=0 Rectangle r2 = new Rectangle(4, 5, 10, 20) // 長方形 (x,y) = (4,5), 幅=10, 高さ=20
これに相当する COBOL コードを次に示します。
working-storage section.
01 r1 object reference.
01 r2 object reference.
...
procedure division.
...
invoke jRectangle "new" returning r1 *> 長方形 (x,y) = 0,0, 幅=0, 高さ=0
invoke jRectangle "new" using 4, 5, 10, 20
returning r2 *> 長方形 (x,y) = (4,5), 幅=10, 高さ=20
COBOL ランタイム システムは、パラメータの数と型を使用して Java クラスの適切なコンストラクタを呼び出します。Java は型付けが強い言語なので、Java クラスが予期する型のパラメータを指定することが大切です。『Java データ型』の章では、COBOL データ型が Java データ型にマップされる方法について説明しています。コピーファイル javatypes.cpy でも、Java データ型に直接対応する、COBOL で使用可能なデータ型のセットが定義されています。Java と COBOL の間でデータを転送する場合は、これらを使用することをお勧めします。
Java オブジェクト上のメソッドはどれでも、メソッドと同じ名前でメッセージを送ることで呼び出すことができます。また、プログラムの Class-Control 段落で宣言したクラス名にメッセージを送ると、Java クラスの静的メソッドを呼び出すこともできます。Java の メソッド名は大文字と小文字を区別するので、COBOL でのメッセージ名は Java のメソッドの大文字と小文字と一致している必要があります。
Java には、メソッドのオーバーロードという機能があり、渡されるパラメータの数と型に応じて、1 つのメソッド名で異なる実体を定義することができます。COBOL では、この処理を透過的に行うので、常に正しい Java メソッドが呼び出されます。
たとえば、Rectangle クラスには異なる add() メソッドが 3 つあり、それぞれ異なるパラメータを受け取ります。次の Java コードは、長方形の add() メソッドを呼び出すことができる方法を 3 つ示しています。
Rectangle r1 = new Rectangle(0,0,0,0) ; Point pt = new Point(6,6) ; Rectangle r2 = new Rectangle(3,4,9,9) ; r1.add(4,5) ; // r1 を、r1 とポイント 4,5 を含む最小の長方形に変更する r1.add(pt) ; // r1 を、r1 と ポイント pt を含む最小の長方形に変更する r1.add(r2) ; // r1 を r1 と r2 の共用体
これに相当する COBOL は次のようになります。
class-control.
jRectangle is class "$java$java.awt.Rectangle"
jPoint is class "$java$java.awt.Point"
.
working-storage section.
01 r1 object reference.
01 r2 object reference.
01 pt object reference.
procedure division.
invoke jRectangle "new" returning r1
invoke jPoint "new" using 4 5 returning pt
invoke jRectangle "new" using 3 4 9 9 returning r2
invoke r1 "add" using 4 5
invoke r1 "add" using pt
invoke r1 "add" using r2
r2 と pt はどちらもオブジェクト リファレンス型のデータ項目ですが、COBOL ランタイム システムは示された Java オブジェクトの型を判断して正しい Java メソッドを呼び出します。
Object COBOL プロキシで invoke "setname" および "getname" メソッドを使用すると、Java クラスのパブリック メンバーと静的変数にアクセスすることができます。Java では、変数名で大文字と小文字が区別されるため、COBOL コードの name での大文字と小文字の用法が、 Java コードで宣言での用法と一致している必要があります。
たとえば、次の Java クラスにはパブリック変数、 classVal と instVal があります。
public class x {
static int classVal;
int instVal;
};
次の COBOL コードのサンプルでは、静的変数 classVal を設定して、次にメンバー instVal を取り込みます。
$set ooctrl(-f+p)
class-control.
x is class "$Java$x"
.
working-storage section.
copy "javatypes.cpy".
01 anX object reference.
01 anInt jint.
procedure division.
invoke x "setclassVal" using by value 4
invoke x "new" returning anX
invoke anX "getinstVal" returning anInt
Java が発生させた例外は、javexpt クラスに対して挙げられた Object COBOL 例外として COBOL に戻されます。デフォルトの例外の動作は、COBOL ランタイム システムが例外の警告メッセージを表示して、終了します。代わりに、COBOL プログラムに例外ハンドラを追加して、例外をトラップすることもできます。
次の手順は、最初に『OO Programming with Object COBOL』マニュアルの『Exception Handling Frameworks』の章を読んでいることを前提としています。
次の手順で Java 例外をトラップします。
class-control.
...
JavaExceptionManager is class "javaexpt"
ExceptionManager is class "exptnmgr"
Callback is class "callback"
EntryCallback is class "entrycll"
...invoke Callback "new" using anObject z"methodName"
returning aHandler
EntryCallback は次のようになります。
invoke EntryCallback "new" using z"entryPointname"
returning aHandlerinvoke ExceptionManager "register"
using JavaExceptionManager aHandler
これで、Object COBOL Java ドメインを経由して呼び出しているクラスから発生した Java 例外はすべてこの例外ハンドラに送られます。
次は、Java プログラムが発生させた例外をキャッチする COBOL プログラムの例です。
$set ooctrl (+p-f)
program-id. ExceptionCatcher.
class-control.
SimpleClass is class "$JAVA$SimpleClass"
EntryCallback is class "entrycll"
JavaExceptionManager is class "javaexpt"
ExceptionManager is class "exptnmgr"
.
working-storage section.
01 theInstance object reference.
01 wsCallback object reference.
local-storage section.
01 filler pic x. *> ローカル エントリ ポイントをコールバックに
*> 使用させるためのダミー記憶域
linkage section.
01 lnkException object reference.
procedure division.
*>---例外ハンドラの設定
invoke EntryCallback "new" using z"JException"
returning wsCallback
invoke ExceptionManager "register" using javaexceptionmanager
wsCallback
*>---クラスのインスタンス化
invoke SimpleClass "new" returning theInstance
display "instantiated"
invoke theInstance "TestException"
display "excepted"
stop run.
entry "Jexception" using lnkException.
invoke lnkException "display"
.
上のプログラムの Local-Storage 節は、再帰を許可するためだけのものです。COBOL ランタイム システムは EntryCallback の呼び出しを再帰的呼び出しとして扱います。Local-Storage 節がない場合は、実行時システムエラーが発生します。
次は、SimpleClass の Java コードです。
import java.lang.* ;
public class SimpleClass {
public SimpleClass() {
}
public void TestException() throws Exception
{
Exception e = new Exception ("テスト エラー" );
throw e;
}
}
オブジェクト COBOL Java ドメインを使用すると、Java オブジェクトへは直接アクセスしていないことになります。つまり、『概要』 の項で説明したとおり、常にプロキシを経由しています。javasup クラスの "getJavaObject" メソッドを使用すると、実際の Java オブジェクトへのポインタを取得することができます。オブジェクト COBOL Java ドメインで提供されていない Java の機能へアクセスする場合は、このメソッドを JNI (Java Native Interface) と合わせて使用することができます。
JNI ポインタを取得するには、javasup クラスで "getEnv" を呼び出します。JNI ポインタは関数テーブルへのポインタです。コピーファイル javatypes.cpy にあるデータ型 JNINativeInterface は、次の例で示すとおり、JNI 関数テーブルの使用を簡単にする構造体を提供します。
working-storage section.
01 JEnv pointer.
01 jobject pointer.
linkage section.
01 lnk-JNINativeInterface JNINativeInterface.
*>
procedure division.
invoke javasup "getEnv" returning jEnv
*> JEnv で渡されたポインタを
*> JNINativeInterface 構造体にマップして、
*> JNI関数を呼び出せるようにします。
set address of lnk-JNINativeInterface to JEnv
*>
これで、JNINativeInterface 型定義によって与えられた名前を使用して JNI 関数を呼び出すことができます。呼び出す例については、『Java からの手続き型 COBOL の呼び出し』の章の 『例外発生の例』 を参照してください。JNI についての詳細は、Sun Microsystems の Java サイトを参照してください。
javasup クラスについての詳細は、『Class Library Reference』マニュアルの『Java Domain Class Library』の項を参照してください。
Java ランタイム環境には、不要なオブジェクトを自動的に破棄するガーベッジコレクタがあります。ガーベッジコレクタは、他のオブジェクトに参照されていないオブジェクトを削除します。COBOL プログラムで Java オブジェクトへのプロキシを保持すると、COBOL ランタイム システムが Java オブジェクトへの参照を持ち、Java ガーベッジコレクタがオブジェクトを削除するのを防ぎます。
Java オブジェクトの使用を終えた場合は、そのオブジェクトへの参照を解放してガーベッジコレクタがそのオブジェクトを削除できるようにする必要があります。参照を解放しないと、アプリケーションにメモリ リークが発生します。次の手順でオブジェクトを終了します。
invoke javaobject "finalize" returning javaobject
ここで、returning のパラメータは重要です。パラメータを指定しないと、COBOL ランタイム システムは、COBOL プロキシを破棄する代わりにメッセージを実際の Java オブジェクトに渡します。メッセージが Java オブジェクトに渡された場合は、次の関数が呼び出されます。
public void finalize()
この関数は、すべての Java クラスによって継承または実行され、オブジェクトを破棄する前に Java ガーベッジコレクタに呼び出されます。
万一 Java クラスが、値を戻す finalize() メソッドを実行した場合には、代わりに次の "delete" メソッドを使用して Object COBOL プロキシを破棄してください。
invoke javaobject "delete" returning javaobject
Copyright © 2002 Micro Focus International Limited. All rights reserved.
本書、ならびに使用されている 固有の商標と商品名は国際法で保護されています。
![]() |
Java からの手続き型 COBOL の呼び出し | Java からのオブジェクト COBOL の呼び出し |