z/OS での共有ライブラリーの使用例

この例では、z/OSシステム上のJava™アプリケーションでネイティブ共有ライブラリを使用する手順について説明します。

このタスクについて

このタスクは、ネイティブ共有ライブラリ内のC関数をロードして呼び出すJavaアプリケーションを作成する方法を示します。

手順

  1. サンプル・アプリケーション「Sample.java作成する:
    public class Sample {
        /**
         * A static class initialization block that is run when this class
         * is first loaded. Here, try to load the target libSample.so shared library
         * that implements the printFromNative() method declared later.
         */
        static {
            try {
                System.loadLibrary("Sample");
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }
        
        /**
         * Prints a message to STDOUT.
         * The 'native' keyword indicates that this method is implemented in native code,
         * callable through the Java Native Interface (JNI).
         */
        public static native void printFromNative();
    
        public static void main(String[] args) {
            // Invoke the native method
            Sample.printFromNative();
        }
    }

    このJavaアプリケーションは、静的ネイティブ・メソッド'Sample.printFromNative()を宣言し、'mainメソッドからこのネイティブ・メソッドを呼び出している。

    Sampleクラスが最初にロードされたときに実行される静的クラス初期化ブロックの間に、'System.loadLibrary("Sample")コールはターゲット・ネイティブ・ライブラリ'libSample.soをロードする。
    注意:'System.loadLibrary(libname)APIは、指定したライブラリ名に接頭辞'libと接尾辞'.soを付加する。 SDKは、'LIBPATH環境変数で指定されたライブラリパス内でターゲット共有ライブラリを検索する。 対象となるネイティブ共有ライブラリーがMVSデータセットの場合、または特定の絶対パスやライブラリー名がある場合は、代わりに「System.load(filename)APIを使用する。
  2. アプリケーションの Java 部分が完成したため、次のようにコンパイルできます。
    javac Sample.java
  3. javac -h コマンドを使用して、ネイティブ・コードのヘッダー・ファイルを作成します。
    javac -h . Sample.java
    このコマンドは、ネイティブ・アプリケーションの実装に適切なJNIメソッド・シグネチャを持つ、「Sample.h」と呼ばれるCヘッダー・ファイルを生成する。
  4. Sample.cという名前のファイルを作成します。
    #include <stdio.h>
    #include "Sample.h"
    
    JNIEXPORT void JNICALL Java_Sample_printFromNative(JNIEnv * env, jclass cls) {
      printf( "Printing from native\n" );
    }
    このファイルは、Java Sample.printFromNative() メソッドの C ネイティブ実装を提供します。
  5. 'Sample.c をコンパイルし、リンクし、共有ライブラリ 'libSample.so にバインドする。 XL C/C++またはOpen XL C/C++コンパイラを使用することができます。

    XL C/C++コマンド
    31ビット・アプリケーションの場合:
    xlc -W "l,xplink,dll" -W "c,langlvl(extended),float(ieee),xplink,dll,exportall" -o libSample.so -I/$JAVA_HOME/include Sample.c  /$JAVA_HOME/lib/s390x/j9vm/libjvm.x
    ここで、$JAVA_HOMEはIBMSDKインストール済み環境のJAVA_HOMEパスです。

    64ビット・アプリケーションの場合:

    xlc -q64 -W "l,dll" -W "c,langlvl(extended),float(ieee),dll,exportall" -o libSample.so -I$JAVA_HOME/include -I$JAVA_HOME/include/zos Sample.c $JAVA_HOME/lib/j9vm/s390x/libjvm.x

    ここで、$JAVA_HOMEはIBMSDKインストール済み環境のJAVA_HOMEパスです。 ヘッダーファイル'jni.hは'$JAVA_HOME/include下に存在し、'libjvm.xは'$JAVA_HOME/lib/s390x/j9vmにある。

    コンパイルコマンドとリンクコマンドの「XL C/C++固有の要素は以下の通り:
    表 1. XL C/C++コマンド固有の要素
    オプション 説明
    xlc - カスタマイズ可能構成ファイルを使用したコンパイラー呼び出し XL Cコンパイラを実行するコマンド。
    -q64 オプションは64ビットのみ有効。 AMODE64 プラットフォーム用のターゲット共有ライブラリーをコンパイルするようにコンパイラーに指示します。
    --W"l,xplink,dll" オプション-Wは、コンパイラーのリンク・フェーズに渡されます。 リンカは共有ライブラリ '.soファイル, and uses the high-performance linkage XPLINK を作成する。
    --W"c,langlvl(拡張)、
    float(ieee)、
    xplink,
    dll,exportall"
    オプション-Wは、コンパイラーのコンパイル・フェーズに渡されます。
    • langlvl(extended)は、long longなどの JNIヘッダー・ファイルによって使用される言語拡張機能を使用可能にします。
    • float(ieee) は、Java 言語の float プリミティブ型および double プリミティブ型に一致する 2 進 IEEE754 浮動小数点数および命令を生成するようにコンパイラーに指示します。
    • xplink、高性能リンケージXPLINKを使うようにコンパイラに指示する。 31ビット・プラットフォームでは、言語環境は他のリンケージ(システム・リンケージなど)への移行をサポートするが、その際には別のパス長が必要となる。
    • dllは、DLLコードを作成するようにコンパイラーに指示します。 DLL コードは、 関数と外部変数をエクスポートまたはインポートできます。
    • exportallは、共用ライブラリー内の呼び出し関数が外部プログラムによって呼び出し可能であることを指定します。
    Open XL C/C++コマンド
    例:
    ibm-clang -m64 -fvisibility=default -o libSample.so -I$JAVA_HOME/include -I$JAVA_HOME/include/zos Sample.c $JAVA_HOME/lib/j9vm/libjvm.x

    ここで、$JAVA_HOMEはIBMSDKをインストールしたJAVA_HOMEパスです。

    コンパイルコマンドとリンクコマンドの「Open XL C/C++固有の要素は以下の通り:
    表 2. Open XL C/C++コマンド固有の要素
    オプション 説明
    イブム・クラング Open XLCコンパイラを実行するコマンド。
    -m64 AMODE64 プラットフォーム用のターゲット共有ライブラリーをコンパイルするようにコンパイラーに指示します。 64ビットのみ。
    -fvisibility=デフォルト このオプションは、コンパイル・ユニット内のすべての外部定義関数と変数をエクスポートし、DLLアプリケーションがそれらを使用できるようにします。
    コンパイルコマンドとリンクコマンドの残りの共有要素は以下の通り:
    表 3. XLとOpen XLの共通要素
    オプション 説明
    -o libSample.so ビルドしたい共有ライブラリの出力ファイルです。 名前('libと'.so間のテキスト)は、'System.load(filename)または'System.loadLibrary(filename)Java APIに提供した名前と一致しなければならない。
    --I デフォルト・ディレクトリに加えて、$JAVA_HOME /includeディレクトリのヘッダー・ファイル(この場合はJNIヘッダー・ファイル)を探すようにコンパイラーに指示します。 JAVA_HOMEをIBMSDKをインストールしたJAVA_HOMEパスに変更します。
    --I デフォルトのディレクトリに加えて、$JAVA_HOME /include/zosディレクトリでヘッダ・ファイル(この場合はJNIヘッダ・ファイル)を探すようにコンパイラに指示します。
    Sample.c C プログラム。
    $JAVA_HOME/lib/j9vm/libjvm.x ネイティブコードがJNIとInvocation APIをリンクして解決できるようにするsidedeckファイル。
  6. Sample アプリケーションを実行します。
    System.loadLibraryJava APIを使ってターゲット共有ライブラリを指定したので、 'LIBPATH環境変数か'java.library.pathプロパティのどちらかに、'libSample.soライブラリが存在するディレクトリが含まれていることを確認する必要がある。
    例:
    LIBPATH=. java Sample
    または
    java -Djava.library.path=. Sample
    プログラムは、以下のメッセージを出力します。
    Printing from native

結果

これで、同じフレームワークを使ってJavaアプリケーションからネイティブ共有ライブラリにアクセスできるようになった。