このサンプル・プログラムは、今までのサンプルと若干異なります。 このサンプルでは、まず PL/I が Java 呼び出し API を介して Java を呼び出し、組み込み Java 仮想マシン (JVM) を作成します。次に PL/I が、ストリングを渡して Java メソッドを呼び出します。そ して、Java メソッドはそのストリングを表示します。
PL/I サンプル・プログラムは createJVM.pli という名前で、このサンプル・プログラムによって呼び出される Java メソッドは javaPart.java に含まれています。
このサンプルは PL/I ネイティブ・メソッドを使用しないため、それを宣言する必要がありません。 その代わり、このサンプルの Java 部分には単純な Java メソッドが 1 つ含まれています。
javaPart クラスには、ステートメントが 1 つだけ含まれます。 このステートメントは、Java から「Hello World...」という短いメッ セージを出力し、PL/I プログラムから渡されたストリングを付け足します。クラス全体は、図 86 に示されています。
// Receive a string from PL/I then display it after saying "Hello"
public class javaPart {
public static void main(String[] args) {
System.out.println("From Java - Hello World... " + args[0]);
}
}Java コードをコンパイルするコマンドは、次のようになります。
javac javaPart.java
PL/I "Hello World" サンプル・プログラムの作成についての説明の大部分が、 このプログラムにも当てはまります。 しかし、このサンプルでは PL/I は Java を呼び出すため、考慮する必要のある点が他にもあります。
このサンプルでは PL/I プログラムが Java を呼び出すため、PL/I プログラムは MAIN になります。 この PL/I プログラムの外部名は参照されないため、考慮する必要はありません。
サンプル・プログラムの完全なプロシージャー・ステートメントは、 次のとおりです。
createJVM: Proc Options(Main);
Java ネイティブ・インターフェースの PL/I 定義を含む 2 つの PL/I インクルード・ファイルは、ibmzjni.inc およびこれにインクルードされる ibmzjnim.inc です。このサンプルで PL/I が Java を呼び出すとしても、これらのインクルード・ファイルはやはり必要です。これらのインクルード・ファイルは、次のステートメントとともに組み込まれています。
%include ibmzjni;
ibmzjni および ibmzjnim インクルード・ファイルは、 PL/I SIBMZSAM データ・セットの中に提供されています。
この PL/I サンプル・プログラムは Java を呼び出すため、Java ライブラリーにリンクできるようにする必要があります。Java ライブラリーは XPLINK とリンクしていますが、PL/I モジュールはリンクしていません。PL/I は現在でも、XPLINK ライブラリーとリンクしてそれを呼び出すこと ができますが、PLIXOPT 変数を使用して、XPLINK=ON ランタイム・オプションを指定する必要があります。 PLIXOPT 変数の宣言は、以下のようになります。
Dcl PLIXOPT Char(40) Varying Ext Static Init( 'XPLINK(ON)'e );
PLIXOPT の使用法については、「z/OS 言語環境プログラム プログラミングの手引き」を参照してください。
この PL/I サンプル・プログラムは、Java 呼び出し API JNI_CreateJavaVM を呼び出して、自身の組み込み JVM を作成します。この API には、図 87 に示されているような、セットアップおよび初期化を正しく行うための特定の構造体が必要です。 まず、JNI_GetDefaultJavaVMInitArgs が、デフォルトの初期化オプションを取得するために呼び出されます。次に、これらのデフォルト・オプションが、java.class.path 情報の追加により変更されます。最後に、JNI_CreateJavaVM が組み込み JVM を作成するために呼び出されます。
完全な PL/I プログラムは、図 87 に示してあります。 このサンプル PL/I プログラムは、JNI を介していくつかの呼び出しを 行います。
このサンプルでは、Java オブジェクト (この場合は新しく作成された JVM) への参照は渡されませんが、代わりに JNI_CreateJavaVM API への呼び出しから戻されます。PL/I プログラムはこの参照を使用して、JVM から情報を取得します。情報の最初の部分は、呼び出す Java メソッドを含むクラスです。 このクラスは、FindClass JNI 関数を使用して検出されます。 クラス値が GetStaticMethodID JNI 関数によって使用され、呼び 出される Java メソッドの ID が取得されます。
この Java メソッドを呼び出す前に、PL/I ストリングを Java が認識できるフォーマットに変換する必要があります。PL/I プログラムでは、ストリングは ASCII フォーマットで保持されます。 Java ストリングは UTF フォーマットで保管されます。さらに、Java ストリングは、PL/I プログラマーが認識するような意味では真にストリングではありませんが、それ自体 Java クラスであり、メソッドを通じてのみ変更できます。 NewStringUTF JNI 関数を使用することにより、Java ストリング配列を作成します。この関数は、UTF に変換された PL/I ストリングを含む myJString という Java オブジェクトを戻します。 次に、myJString オブジェクトへの参照を渡して、NewObjectArray JNI 関数を呼び出すことにより、Java オブジェクト配列を作成します。 この関数は、Java メソッドに表示させるストリングを含む Java オブジェクト配列への参照を返します。
これで、CallStaticVoidMethod JNI 関数を使用して Java メソッドを呼び出すことができました。次に、Java メソッドは、渡されたストリングを表示します。 ストリングを表示した後、PL/I プログラムは、DestroyJavaVM JNI 関数を使用して組み込み JVM を破棄し、PL/I プログラムが完了します。
PL/I プログラムの完全なソースは、図 87 にあります。
*Process Limits( Extname( 100 ) ) Margins( 1, 100 );
*Process LangLVL( SAA2 ) Margins( 1, 100 ) ;
*Process Display(STD) Rent;
*Process Default( ASCII ) Or('|');
createJVM: Proc Options(Main);
%include ibmzjni;
Dcl myJObjArray Type jobjectArray;
Dcl myClass Type jclass;
Dcl myMethodID Type jmethodID;
Dcl myJString Type jstring;
Dcl myRC Fixed Bin(31) Init(0);
Dcl myPLIStr Char(50) Varz
Init('... a PLI string in a Java Virtual Machine!');
Dcl OptStr Char(1024) Varz;
Dcl myNull Pointer;
Dcl VM_Args Like JavaVMInitArgs;
Dcl myOptions Like JavaVMOption;
Dcl PLIXOPT Char(40) Varying Ext Static Init( 'XPLINK(ON)'e );
Display('From PL/I - Beginning execution of createJVM...');
/* Important difference between J1.3 and J1.4: */
/* J1.3 requires VM_Args.version = JNI_VERSION_1_2; */
/* J1.4 requires VM_Args.version = JNI_VERSION_1_4; */
VM_Args.version = JNI_VERSION_1_4;
myRC = JNI_GetDefaultJavaVMInitArgs( addr(VM_Args) );
OptStr = "-Djava.class.path=.:";
myOptions.theOptions = addr(OptStr);
VM_Args.nOptions = 1;
VM_Args.JavaVMOption = addr(myOptions);
/* Create the Java VM */
myrc = JNI_CreateJavaVM(
addr(JavaVM),
addr(JNIEnv),
addr(VM_Args) );
/* Get the Java Class for the javaPart class */
myClass = FindClass(JNIEnv, "javaPart");
/* Get static method ID */
myMethodID = GetStaticMethodID(JNIEnv, myClass,"main",
"([Ljava/lang/String;)V" );
/* Create a Java String Object from the PL/I string. */
myJString = NewStringUTF(JNIenv, myPLIStr);
myJObjArray = NewObjectArray(JNIEnv, 1,
FindClass(JNIEnv,"java/lang/String"), myJString);
Display('From PL/I - Calling Java method in new JVM from PL/I...');
Display(' ');
myNull = CallStaticVoidMethod(JNIEnv, myClass,
myMethodID, myJObjArray );
/* destroy the Java VM */
Display(' ');
Display('From PL/I - Destroying the new JVM from PL/I...');
myRC = DestroyJavaVM( JavaVM ); /* rc = -1 is OK */
end;次のコマンドを使用して、PL/I サンプル・プログラムをコンパイルします。
pli -c createJVM.pli
次のコマンドを使用して、生成された PL/I オブジェクト・デックを Java ライブラリーにリンクします。
c89 -o createJVM createJVM.o $JAVA_HOME/bin/classic/libjvm.x
$JAVA_HOME 環境変数への参照に注意してください。 この変数は、ご使用の Java 1.4 製品がインストールされているディレクトリーを指す必要があります。例えば、ご使用の環境でこの変数をセットアップするには、次のコマンドを使用します。
export JAVA_HOME="/usr/lpp/java/J1.4"
このケースでは、Java 1.4 製品が /usr/lpp/java/J1.4 にインストールされていることが前提となっています。
次のコマンドを使用して、PL/I - Java サンプル・プログラムを実行します。
createJVM
サンプル・プログラムの出力は次のとおりです。
From PL/I - Beginning execution of createJVM... From PL/I - Calling Java method in new JVM from PL/I... From Java - Hello World... ... a PLI string in a Java Virtual Machine! From PL/I - Destroying the new JVM from PL/I...