JNI 実行時リンク

Java™ Native Interface (JNI) を使用すると、動的ネイティブ・ライブラリーおよび静的ネイティブ・ライブラリーへのランタイム・リンクが可能になります。

プラットフォーム固有の情報については、以下のセクションを参照してください。

AIX システムに固有の情報

ランタイム・リンクの場合、-brtlローダー・オプションを使用してアプリケーションをリンクできます。 実行時リンクによって記号の競合が起こる場合、アプリケーションは、アプリケーション側で記号の名前を変更するか、実行時リンクをオフにすることで、競合を解決する必要があります。

AIX でのダイナミック・リンク

ネイティブ・ライブラリーを動的にリンクするには、ネイティブ・メソッド (Java によって呼び出される C または C++ 関数) を AIX 共有オブジェクト (動的にロードされるライブラリー) にコンパイルする必要があります。 例えば、ネイティブ・メソッドをファイル nm.c に保管していれば、 次のコマンドで共有オブジェクトを作成できます。
cc_r -qmkshrobj [-qarch=ppc | -q64] -Ijava_install_dir/include 
-o libnm.a nm.c
-qmkshrobjオプションは、ランタイム・リンクを使用不可にします。 共有オブジェクト・ファイル、ランタイム・リンク、およびccコマンド行オプションとldコマンド行オプションの使用について詳しくは、以下を参照してください。

ネイティブ・メソッドを使用する Java プログラムを実行する前に、ネイティブ・メソッドの共有オブジェクトを保持するディレクトリーのリストが LIBPATH に含まれていることを確認してください。 AIX 共有オブジェクトの作成について詳しくは、 AIX を参照してください。 https://www.ibm.com/redbooks にアクセスして、「SG245674」を検索してください。

JNIネイティブ・コード・プログラムでセットアップID 属性またはセットID属性を設定すると、その設定によって有効なLIBPATH環境変数が変更されます。 この変更のために、それらのプログラムで予期しない動作または正しくない動作が行われる場合があります。 この使用法について詳しくは、「 Developing and Porting C and C++ Applications on AIX 」( http://www.redbooks.ibm.com/abstracts/sg245674.htmlのセクション 2.3.3) を参照してください。

JNI 呼び出し API を使用して Java 仮想マシンを作成し、Java コードを呼び出す C または C++ プログラムをビルドする場合は、 -L オプションを使用して以下のタスクを実行します。

  • /usr/libおよび/libを、共有オブジェクトを検索するディレクトリーのリストに追加します。 これらのディレクトリーに保管されている共有オブジェクトは、すべてのプログラムが必要とします。
  • Java java_install_dir/jre/lib および java_install_dir/jre/lib/j9vm ディレクトリーを、共有オブジェクトを検索するディレクトリーのリストに追加します。 これらのディレクトリーには、Java 共有ライブラリーが含まれています。 libjvm.so とのリンク (-ljvm オプションを使用) も必要です。

例えば、以下のコードは、JNI呼び出しAPIを使用するCプログラム(invAPITest.c)をビルドします。

cc_r [-qarch=pwr4 | -q64] -Ijava_install_dir/include 
	-o invAPITest 
	-L/usr/lib 
	-L/lib 
	-Ljava_install_dir/jre/lib/j9vm 
	-Ljava_install_dir/jre/lib 
	-ljvm invAPITest.c

JNI 呼び出し API を使用して Java クラスを実行する C または C++ プログラムを実行する場合は、JVM がクラス・ファイルを検出できるようにクラスパスが正しくセットアップされていることを確認してください。 Java ブート・クラスパスを変更する場合は、アプリケーションの実行に必要な SDK ファイルを含めてください。

JNI呼び出しAPIを使用しているCまたはC++プログラムが-bM:URオプションでビルドされたものかどうかを判断するには、次のコマンドを使用します。

dump [-X64] -ov <program name> 

以下のような出力が生成されます。

>dump -X64 -ov <program name>
                        ***Object Module Header***
# Sections      Symbol Ptr      # Symbols       Opt Hdr Len     Flags
         4      0x0001a728           1305               120     0x1002
Flags=( EXEC DYNLOAD DEP_SYSTEM )
Timestamp = "14 Oct 03:26:43 2005"
Magic = 0x1f7  (64-bit XCOFF)

                        ***Optional Header***
Tsize        Dsize       Bsize       Tstart      Dstart
0x000127f8  0x00001b80  0x00000470  0x1000001f8  0x1100009f0

SNloader     SNentry     SNtext      SNtoc       SNdata
0x0004      0x0002      0x0001      0x0002      0x0002    

TXTalign     DATAalign   TOC         vstamp      entry
0x0005      0x0003      0x110002158  0x0001      0x110002040

maxSTACK     maxDATA     SNbss       magic       modtype
0x00000000  0x00000000  0x0003      0x010b        UR
If themodtype次と等しくないURLDR_CNTRL 環境変数を使用すると、 -bM:UR バインダー・オプションを指定してコンパイルされたかのようにプログラムを動作させることができます。 例:
export LDR_CNTRL=USERREGS

LDR_CNTRLで複数のオプションを指定する必要がある場合は、それらのオプションを@記号で区切ります。

JVM によって作成される Java スレッドは、 AIXでサポートされる POSIX pthreads モデルを使用します。 現在、この方法はカーネル・スレッドとの 1 対 1 マッピングを基にしています。 JNI プログラムを作成するときに、独自のプログラムで pthread を作成する場合は、1 対 1 のスレッド・モデルおよびシステム競合スコープを指定して実行する必要があります。 この動作は、次の環境設定を使用して制御できます。
export AIXTHREAD_SCOPE=S

もう 1 つのオプションは、スレッドの作成時に AIX pthread_attr_setscope 関数を使用して、スレッドのスコープ属性を PTHREAD_SCOPE_SYSTEM に事前設定することです。

ネイティブ・メソッドは、以下の方法で保管できます。
共有オブジェクト
共有オブジェクトは、 XCOFF ヘッダーで SRE (共有再使用可能) ビットを設定した単一のオブジェクト・ファイルです。 SRE ビットは、このファイルが動的にリンクされることをリンカーに通知します。 これらのファイルは通常、<filename> .oという形式の名前になりますが、リンカーが-lnameオプションを使用して検索できるようにlib<name> .aという名前にすることもできます。ただし、これらはアーカイブ・ライブラリー・ファイルではありません。
共有ライブラリー
共有ライブラリーは、 1 つ以上のアーカイブ・メンバーがその中の共有オブジェクトである「ar」形式のアーカイブ・ライブラリーです。 このライブラリーには、静的にリンクされた非共有オブジェクト・ファイルも含まれることに注意してください。 共有ライブラリーの名前はlib<name> .aの形式です。 このフォームにより、リンカーは-lnameオプションを使用してライブラリーを検索できます。

詳しくは、 AIX の資料を参照してください。

プログラムは、サブルーチンの dlopen() ファミリーを使用するなどして、共有ライブラリーおよび共有オブジェクトに動的にリンクすることもできます。 JVM は、ネイティブ・ライブラリー (例えば、System.load()System.loadLibrary()Runtime.getRuntime().load()Runtime.getRuntime().loadLibrary()) をロードするときにこの方法でリンクします。

dlopen については、 dlopen サブルーチンを参照してください。

AIX のロードとリンクのメカニズムについては、「 AIX リンクとロードのメカニズム」を参照してください。

AIX 共有ライブラリーをロードするには、以下を呼び出します。
System.loadLibrary("<library>(<member>)")
ここで、<library> は共有ライブラリー・アーカイブの名前、<member> はアーカイブ・メンバーの名前です。 例:
System.loadLibrary("libShared.a(libSample.o)")
注: ネイティブ・ライブラリーのダイナミック・リンクが正常に機能するようにするために、オプションで、ライブラリーにライフサイクル関数 JNI_Onload() および JNI_OnUnload() を実装することができます。 JNI_Onload() を実装している場合、ネイティブ・ライブラリーは、これをエクスポートする必要があります。そうしないと、ランタイムから認識できないため、JVM は、ライブラリーで必要なのは JNI バージョン JNI_VERSION_1.1 のみであると想定します。 JNI_OnUnload() が実装されている場合は、これもエクスポートする必要があります。 JNI_Onload() が実装されてエクスポートされると、最新の JNI バージョン (JNI_VERSION_1.8 など) が返されます。

AIX での静的リンク

JNI ライブラリーは、動的にリンクするのに加え、静的にもリンクできます。 静的ライブラリーは、呼び出し API を使用して JVM プロセスを起動するカスタム・ランチャーのイメージに、組み合わせることができます。

testlibA および testlibB の 2 つの静的ライブラリーを考えてみます。 testlibA ライブラリをJavaプログラムにロードしようとして、 System.loadLibrary("testlibA") のようなコマンドを使用した場合、JVMはまず、起動する実行プログラムのイメージから JNI_OnLoad_testlibA( という名前のルーチンを探します。このルーチンが見つかると、JVMは静的にバインドされたライブラリを使用してJNI定義を提供します。 ルーチンが見つからないと、JVM は、-Djava.library.path (または LIBPATH) によって指定されたパスで探すことにより、testlibA ライブラリーを動的にロード (libtestlibA.so など) するためにフォールバックします。

AIXでは、 -brtlを指定してランタイム・リンクを使用可能にするほかに、オプション -bexpall を指定してビルドする必要があります。 このプロセスによりランチャーは、シンボル (JNI_OnLoad_testlibA() など) をエクスポートするのに加え、実行可能プログラム (JVM の実行可能プログラムなど) によってロードされた共有ライブラリーでシンボルを検索できるようにします。 JVM で静的にリンクを行う場合、JVM は、動的リンクで試行する前に実行可能プログラムを検索できなければなりません。

実行可能プログラムは、次のコマンドを実行し、静的ライブラリーを使用してビルドすることもできます。
$ cc_r -qpic -brtl -bexpall -brtl testlibA.o testlibB.o -o <launcher>
ここで、 < launcher> は、 testlibA ライブラリーと testlibB ライブラリーのイメージ、および呼び出し API を介して JVM を起動する Java ランチャーを含む実行可能プログラムの名前です。

ライブラリLのライブラリ初期化ルーチン JNI_OnLoad_L, は、戻り値を返さなければなりませんJNI_VERSION_1_8(0x00010008).

Linux システムに固有の情報

実行時リンクによって記号の競合が起こる場合、アプリケーションは、アプリケーション側で記号の名前を変更するか、実行時リンクをオフにすることで、競合を解決する必要があります。

Linux でのダイナミック・リンク

JNI 呼び出し API を使用して Java 仮想マシンを作成し、Java コードを呼び出す C または C++ プログラムをビルドする場合は、 -L オプションを使用して以下のタスクを実行します。

  • /usr/libおよび/libを、共有オブジェクトを検索するディレクトリーのリストに追加します。 これらのディレクトリーに保管されている共有オブジェクトは、すべてのプログラムが必要とします。
  • Java java_install_dir/jre/lib および java_install_dir/jre/lib/j9vm ディレクトリーを、共有オブジェクトを検索するディレクトリーのリストに追加します。 これらのディレクトリーには、Java 共有ライブラリーが含まれています。 libjvm.so とのリンク (-ljvm オプションを使用) も必要です。

例えば、以下のコードは、JNI呼び出しAPIを使用するCプログラム(invAPITest.c)をビルドします。

cc [-m32|-m64] -Ijava_install_dir/include 
	-o invAPITest 
	-L/usr/lib 
	-L/lib 
	-Ljava_install_dir/jre/lib/j9vm 
	-Ljava_install_dir/jre/lib 
	-ljvm invAPITest.c

JNI 呼び出し API を使用して Java クラスを実行する C または C++ プログラムを実行する場合は、JVM がクラス・ファイルを検出できるようにクラスパスが正しくセットアップされていることを確認してください。 Java ブート・クラスパスを変更する場合は、アプリケーションの実行に必要な SDK ファイルを含めてください。

実行時に Java アプリケーションが解決する必要がある関数を JNI ライブラリーがエクスポートするようにするには、 nm ツールを使用してライブラリーを調べることができます。 例えば、JNI ルーチン fooImpl および barImpl を含む libjnitest.so という名前の JNI ライブラリーは、以下のシンボルをエクスポートする必要があります。

$ nm libjnitest.so
000537d0 T Java_mypackage_SampleClass_fooImpl
0004f020 T Java_mypackage_SampleClass_barImpl

同様に、コマンド objdump -T では、以下に示す、共有ライブラリー内のエクスポートされるシンボルをリストします。

000537d0  g    DF .text  00000040  Base        0x60 
Java_mypackage_SampleClass_fooImpl
0004f020  g    DF .text  00000254  Base        0x60 
Java_mypackage_SampleClass_barImpl
ネイティブ・メソッドは、以下の方法で保管できます。
共有ライブラリー
Linux 上の共有ライブラリー (または共有オブジェクト) は、ビルド時 (リンク時リンク) または実行時 (実行時リンク) にリンクできるダイナミック・リンク・ライブラリーです。 共有ライブラリーへのリンク時リンクはリンカー・エディター・ツール ld を使用して行うのに対し、実行時リンクでは関数の dlopen(3) ファミリーを使用します。

プログラムは、サブルーチンの dlopen() ファミリーを使用するなどして、共有ライブラリーおよび共有オブジェクトに動的にリンクすることもできます。 JVM は、ネイティブ・ライブラリー (例えば、System.load()System.loadLibrary()Runtime.getRuntime().load()Runtime.getRuntime().loadLibrary()) をロードするときにこの方法でリンクします。

dlopen(3)については、 Linux のマニュアル資料を参照し、 dlopenを検索してください。

注: ネイティブ・ライブラリーのダイナミック・リンクが正常に機能するようにするために、オプションで、ライブラリーにライフサイクル関数 JNI_Onload() および JNI_OnUnload() を実装することができます。 JNI_Onload() を実装している場合、ネイティブ・ライブラリーは、これをエクスポートする必要があります。そうしないと、ランタイムから認識できないため、JVM は、ライブラリーで必要なのは JNI バージョン JNI_VERSION_1.1 のみであると想定します。 JNI_OnUnload() が実装されている場合は、これもエクスポートする必要があります。 JNI_Onload() が実装されてエクスポートされると、最新の JNI バージョン (JNI_VERSION_1.8 など) が返されます。

Linux での静的リンク

JNI ライブラリーは、動的にリンクするのに加え、静的にもリンクできます。 静的ライブラリーは、呼び出し API を使用して JVM プロセスを起動するカスタム・ランチャーのイメージに、組み合わせることができます。

testlibA および testlibB の 2 つの静的ライブラリーを考えてみます。 testlibA ライブラリをJavaプログラムにロードしようとして、 System.loadLibrary("testlibA") のようなコマンドを使用した場合、JVMはまず、起動する実行プログラムのイメージから JNI_OnLoad_testlibA( という名前のルーチンを探します。このルーチンが見つかると、JVMは静的にバインドされたライブラリを使用してJNI定義を提供します。 ルーチンが見つからないと、JVM は、-Djava.library.path (または LD_LIBRARY_PATH) によって指定されたパスで探すことにより、testlibA ライブラリーを動的にロード (libtestlibA.so など) するためにフォールバックします。

Linux では、ランチャーがシンボル( JNI_OnLoad_testlibA( など)をエクスポートし、また実行プログラム(JVMなど)によって読み込まれる共有ライブラリがシンボルを検索できるように、 -rdynamic オプションを指定してビルドする必要があります。 JVM で静的にリンクを行う場合、JVM は、動的リンクで試行する前に実行可能プログラムを検索できなければなりません。 -rdynamic を指定しないと、静的でないシンボルは、実行可能プログラムから引き続きエクスポートされますが、実行可能プログラムによりロードされた共有ライブラリーから認識されません。 -rdynamic の使用例は次のとおりです。

$ cc -rdynamic testlibA.o testlibB.o -o <launcher>

ライブラリLのライブラリ初期化ルーチン JNI_OnLoad_L, は、戻り値を返さなければなりませんJNI_VERSION_1_8(0x00010008).

Windows システムに固有の情報

実行時リンクによって記号の競合が起こる場合、アプリケーションは、アプリケーション側で記号の名前を変更するか、実行時リンクをオフにすることで、競合を解決する必要があります。

Windows でのダイナミック・リンク

JNI 呼び出し API を使用して Java 仮想マシンを作成し、Java コードを呼び出す C または C++ プログラムをビルドする場合は、リンカー・オプション /link /LIBPATH を使用して以下のタスクを実行します。

  • Java java_install_dir\jre\bin\ および java_install_dir\jre\bin\j9vm ディレクトリーを、共有オブジェクトを検索するディレクトリーのリストに追加します。 これらのディレクトリーには、Java 共有ライブラリーが含まれています。 jvm.dll とのリンク (-ljvm オプションを使用) も必要です。

Windows では、コマンド行コンパイラー cl.exeに特別なオプションは必要ありません。 通常、Microsoft コンパイラー (VC + + など) が使用されます。コンパイラー・オプションについて詳しくは、使用されているコンパイラーの資料を参照してください。 デフォルトでは、VC++ は、環境変数 %LIB% で示される場所にあるライブラリーを使用します。 この変数は、ライブラリーをリンクするための検索パスの 1 つとして、常に VC++ SDK の \lib サブディレクトリーを指す必要があります。

呼び出し API テストをビルドするための標準的なコマンド・ブロックを以下に示します。
cl.exe /I java_install_dir\jre\include
	/FeinvAPITest 
	invAPITest.c 
	/link /LIBPATH:java_install_dir\jre\bin\j9vm 
	/LIBPATH:java_install_dir\jre\bin

JNI 呼び出し API を使用して Java クラスを実行する C または C++ プログラムを実行する場合は、JVM がクラス・ファイルを検出できるようにクラスパスが正しくセットアップされていることを確認してください。 Java ブート・クラスパスを変更する場合は、アプリケーションの実行に必要な SDK ファイルを含めてください。

実行時に Java アプリケーションが解決する必要がある関数を JNI ライブラリーがエクスポートするようにするには、 dumpbin.exe ツール (通常は VC++ SDK インストールの一部) を使用してライブラリーを調べることができます。 例えば、名前が jnitest.dll で、JNI ルーチン fooImpl および barImpl を含む JNI ライブラリーでは、以下のシンボルをエクスポートする必要があります。
C:\>dumpbin.exe /EXPORTS jnitest.dll
Dump of file jnitest.dll

File Type: DLL

      Section contains the following exports for JNITEST.dll

00000000 characteristics
5412A472 time date stamp Fri Sep 12 03:44:50 2014
    0.00 version
       1 ordinal base
       5 number of functions
       5 number of names

ordinal hint RVA      name
...
     1   27 0000CE10 Java_mypackage_SampleClass_fooImpl = Java_mypackage_SampleClass_fooImpl
     2   28 000085A0 Java_mypackage_SampleClass_barImpl = Java_mypackage_SampleClass_barImpl
...

dumpbin.exeとそのオプションについて詳しくは、MSDNの資料を参照してください。

ネイティブ・メソッドは、以下の方法で保管できます。
ダイナミック・リンク・ライブラリー
Windows では、JNI メソッドは通常、ダイナミック・リンク・ライブラリー (DLL) と呼ばれる動的ライブラリーに保管されます。 DLL には、別のロード・モジュール (動的ライブラリーや実行可能プログラムなど) から参照できる関数およびデータが含まれています。 ネイティブ・メソッドは DLL に保管され、ビルド時にリンクされるか、リンク・プロセスを介してリンクされるか、または実行時に Windows API LoadLibrary() および LoadLibraryEx() 関数を使用してメソッドを動的にロードすることによってリンクされます。 関数の LoadLibrary() ファミリーについて詳しくは、MSDN の資料を参照してください。
注: ネイティブ・ライブラリーのダイナミック・リンクが正常に機能するようにするために、オプションで、ライブラリーにライフサイクル関数 JNI_Onload() および JNI_OnUnload() を実装することができます。 JNI_Onload() を実装している場合、ネイティブ・ライブラリーは、これをエクスポートする必要があります。そうしないと、ランタイムから認識できないため、JVM は、ライブラリーで必要なのは JNI バージョン JNI_VERSION_1.1 のみであると想定します。 JNI_OnUnload() が実装されている場合は、これもエクスポートする必要があります。 JNI_Onload() が実装されてエクスポートされると、最新の JNI バージョン (JNI_VERSION_1.8 など) が返されます。

Windows での静的リンク

JNI ライブラリーは、動的にリンクするのに加え、静的にもリンクできます。 静的ライブラリーは、呼び出し API を使用して JVM プロセスを起動するカスタム・ランチャーのイメージに、組み合わせることができます。

testlibA および testlibB の 2 つの静的ライブラリーを考えてみます。 testlibA ライブラリをJavaプログラムにロードしようとして、 System.loadLibrary("testlibA") のようなコマンドを使用した場合、JVMはまず、起動する実行プログラムのイメージから JNI_OnLoad_testlibA( という名前のルーチンを探します。このルーチンが見つかると、JVMは静的にバインドされたライブラリを使用してJNI定義を提供します。 ルーチンが見つからないと、JVM は、-Djava.library.path (または PATH) によって指定されたパスで探すことにより、testlibA ライブラリーを動的にロード (testlibA.dll など) するためにフォールバックします。

Windows では、ランチャー実行可能プログラムのビルド中に指定する特別なオプションはありません。

ライブラリLのライブラリ初期化ルーチン JNI_OnLoad_L, は、戻り値を返さなければなりませんJNI_VERSION_1_8(0x00010008).

z/OS システムに固有の情報

実行時リンクによって記号の競合が起こる場合、アプリケーションは、アプリケーション側で記号の名前を変更するか、実行時リンクをオフにすることで、競合を解決する必要があります。

z/OS でのダイナミック・リンク

JNI 呼び出し API を使用して Java 仮想マシンを作成し、Java コードを呼び出す C または C++ プログラムをビルドする場合は、 -L オプションを使用して以下のタスクを実行します。

  • /usr/libおよび/libを、共有オブジェクトを検索するディレクトリーのリストに追加します。 これらのディレクトリーに保管されている共有オブジェクトは、すべてのプログラムが必要とします。
  • Java java_install_dir/jre/lib および java_install_dir/jre/lib/j9vm ディレクトリーを、共有オブジェクトを検索するディレクトリーのリストに追加します。 これらのディレクトリーには、Java 共有ライブラリーが含まれています。 libjvm.so とのリンク (-ljvm オプションを使用) も必要です。

例えば、次のコードは、CプログラムinvAPITest.cをコンパイルして、invAPITestという名前の呼び出し API ランチャーを作成します。

cc [-q32|-q64] -Ijava_install_dir/jre/include 
	-o invAPITest 
	-L/usr/lib 
	-L/lib 
	-Ljava_install_dir/jre/lib/j9vm 
	-Ljava_install_dir/jre/lib 
	-ljvm invAPITest.c

-q32または-q64は、プログラムが作成されるデータ・モデルを指定します。 これらの値を省略すると、デフォルトのデータ・モデルが使用されます。

JNI 呼び出し API を使用して Java クラスを実行する C または C++ プログラムを実行する場合は、JVM がクラス・ファイルを検出できるようにクラスパスが正しくセットアップされていることを確認してください。 Java ブート・クラスパスを変更する場合は、アプリケーションの実行に必要な SDK ファイルを含めてください。

実行時に Java アプリケーションが解決する必要がある関数を JNI ライブラリーがエクスポートするようにするには、 nm ツールを使用してライブラリーを調べることができます。 例えば、名前が libjnitest.so で、JNI ルーチン fooImpl および barImpl を含む JNI ライブラリーでは、以下のシンボルをエクスポートする必要があります。

$nm libjnitest.so
     255552 T Java_mypackage_SampleClass_fooImpl
     255528 T Java_mypackage_SampleClass_barImpl

詳しくは、 コンパイラー・オプションのデフォルトを参照してください。

ネイティブ・メソッドは、以下の方法で保管できます。
ダイナミック・リンク・ライブラリー
IBM Z® システムでは、JNI メソッドは通常、ダイナミック・リンク・ライブラリー (DLL) と呼ばれる動的ライブラリーに保管されます。 DLL には、別のロード・モジュール (動的ライブラリーや実行可能プログラムなど) から参照できる関数およびデータが含まれています。 ネイティブ・メソッドは DLL に保管され、リンク・プロセスを介してビルド時にリンクされるか、実行時に IBM Z API dllload または POSIX準拠 API dlopenを使用してメソッドを動的にロードすることによってリンクされます。 dllload () 関数および dlopen () 関数について詳しくは、「 DLL のロード」を参照してください。

プログラムは、サブルーチンの dlopen() ファミリーまたは dllload() ファミリーを使用するなどして、共有ライブラリーおよび共有オブジェクトに動的にリンクすることもできます。 JVM は、ネイティブ・ライブラリー (例えば、System.load()System.loadLibrary()Runtime.getRuntime().load()Runtime.getRuntime().loadLibrary()) をロードするときにこの方法でリンクします。

これらのサブルーチンについては、 dlopen () および dllload ()を参照してください。

注: ネイティブ・ライブラリーのダイナミック・リンクが正常に機能するようにするために、オプションで、ライブラリーにライフサイクル関数 JNI_Onload() および JNI_OnUnload() を実装することができます。 JNI_Onload() を実装している場合、ネイティブ・ライブラリーは、これをエクスポートする必要があります。そうしないと、ランタイムから認識できないため、JVM は、ライブラリーで必要なのは JNI バージョン JNI_VERSION_1.1 のみであると想定します。 JNI_OnUnload() が実装されている場合は、これもエクスポートする必要があります。 JNI_Onload() が実装されてエクスポートされると、最新の JNI バージョン (JNI_VERSION_1.8 など) が返されます。

z/OS での静的リンク

JNI ライブラリーは、動的にリンクするのに加え、静的にもリンクできます。 静的ライブラリーは、呼び出し API を使用して JVM プロセスを起動するカスタム・ランチャーのイメージに、組み合わせることができます。

testlibA および testlibB の 2 つの静的ライブラリーを考えてみます。 testlibA ライブラリをJavaプログラムにロードしようとして、 System.loadLibrary("testlibA") のようなコマンドを使用した場合、JVMはまず、起動する実行プログラムのイメージから JNI_OnLoad_testlibA( という名前のルーチンを探します。このルーチンが見つかると、JVMは静的にバインドされたライブラリを使用してJNI定義を提供します。 ルーチンが見つからないと、JVM は、-Djava.library.path (または LIBPATH) によって指定されたパスで探すことにより、testlibA ライブラリーを動的にロード (libtestlibA.so など) するためにフォールバックします。

IBM Z システムでは、ビルド時に以下のオプションを指定する必要があります。
  • 実行プログラムがDLLとしてビルドされることを確認するためのWc,DLL
  • 実行プログラムのシンボルがエクスポートされ、プログラムがロードする共有ライブラリから参照できるようにするためのWc,EXPORTALL
これらのオプションによって、ランチャー実行可能プログラムはシンボル (JNI_Onload_testlibA() など) をエクスポートできるようになるため、JVM は動的リンクを試行する前にシンボルを検索できます。
以下の例ではコンパイル行およびリンク行を使用して、静的ライブラリー testlibA および testlibB が、DLL としてビルドされた、すべての記号をエクスポートするランチャーにリンクされるようにします。
cc -c -Wc,DLL,EXPORTALL launcher.c -o launcher.o
cc testlibA.o testlibB.o launcher.o -o launcher

また、EXPORTALLを削除すると、#pragma exportを使用して特定のシンボルをエクスポートすることができます。 詳しくは、 #pragma エクスポートを参照してください。

注: IBM Z システムでは、実行可能プログラムが静的リンクを使用して参照する必要がある JNI ルーチンをパッケージ化する場合、エクスポート・シンボルに加えて、実行可能プログラムをダイナミック・リンク・ライブラリー (DLL) としてビルドする必要があります。 IBM Z 実行可能プログラムが JNI_OnLoad_testlibAを定義してエクスポートするが、それ自体が DLL として作成されていない (つまり、 -Wc,DLL が指定されていない) 場合、実行時に実行可能プログラムからシンボルを解決することができないため、静的リンクは失敗する可能性があります。

ライブラリLのライブラリ初期化ルーチン JNI_OnLoad_L, は、戻り値を返さなければなりませんJNI_VERSION_1_8(0x00010008).