Java 2 SDK 開発ガイド (Solaris 編)

Java Native Interface (JNI)

NMI から JNI への移行

Java 2 SDK Solaris 版は NMI をサポートしません。インストールによっては、NMI は JNI 1.0、JNI は JNI 1.1 と呼ばれます。


注 -

ネイティブメソッドを含むアプリケーションはプラットフォームに依存し、「Write Once Run AnywhereTM」ではありません。このことは、NMI または JNI のどちらが使用されているかに関係ありません。ネイティブメソッドのサポートが変更されても、アプレットには影響しません。


移植

NMI を使用するアプリケーションを JNI インタフェースを使用するように変更するのは簡単です。たとえば、不慣れな技術者でも 2 日ほどで 6000 行の C コードを移植しました。この例では、NMI は少し使われているだけでしたが、使用箇所は広く分散していました。

javah

javah コマンドは、ネイティブメソッドの実装に必要な C ヘッダとソースファイルを生成します。C プログラムは生成されたヘッダとソースファイルを使用して、ネイティブソースコードのオブジェクトのインスタンス変数を参照します。JNI には、ヘッダ情報やスタブファイルは必要ありません。引き続き javah コマンドで jni オプションを使用して、JNI 形式のネイティブメソッドに必要なネイティブメソッド関数プロトタイプを生成することができます。結果は、.h ファイルに書き込まれます。

JDK 1.1 のデフォルトのモードでは、javah コマンドは NMI 出力を生成します。

NMI インタフェースは Java 2 SDK Solaris 版の実装とまったく互換性がないため、Java 2 SDK Solaris 版で -old フラグを使用して、NMI 形式の出力を生成することはできません。Java 2 SDK Solaris 版では、-old フラグは解析され、見つかった場合は、-old not supported メッセージが生成され、javah は終了します。

JNI の一般的な問題

コンパイラに関する制限事項

ネイティブメソッドをコンパイルするときにコンパイラが行うことがある最適化によって、VM を実行できないことがあります。VM はスレッドのスタックにある関数のスタックフレーム検査機能に依存します。このため、ネイティブ関数のコードは、非リーフ関数に対するシステム呼び出し規則の規定にしたがってつねにスタックフレームを作成する必要があります。またフレームポインタレジスタは、つねに有効なスタックフレームを指す必要があります。


注 -

上記の制限事項に違反しているネイティブメソッドは、VM を異常終了させることがあります。


ネイティブの Solaris アプリケーションのリンク

ネイティブの Solaris アプリケーションは、-lthread を使用してリンクしてください。そのようにしないと、不正な動作をすることがあります。

JNI を使用するネイティブアプリケーションをリンクするときは、libc.so ライブラリ (-lc オプション) の前に libthread.so ライブラリ (-lthread オプション) を指定する必要があります。Sun C コンパイラの -mt オプションは、-lthread オプションを自動的に追加します。一般的に -lc オプションは指定しません (デフォルトでリストの末尾になります)。このため、Sun のコンパイラやリンカを使用するときは、かならず -mt または -lthread オプションを指定しなければなりません。

JNI における配列への高速アクセス

Java 2 SDK Solaris 版では、Get*ArrayElements() 呼び出しの代わりに jni_GetPrimitiveArrayCritical() および jni_ReleasePrimitiveArrayCritical() を使用することによって JNI 配列へのアクセスを高速にすることができます。

これらの制限事項があるため、データ固定やコピーを行わずに配列の要素にアクセスすることはできません。詳細は次のサイトを参照してください。

http://java.sun.com/products/jdk/1.2/ja/docs/ja/guide/jni/jni-12.html

共有ライブラリの格納場所

Solaris 2.5.1 または 2.6 ソフトウェアを使用していて、デフォルトの /usr/java1.2 以外の場所に JDK をインストールした場合、JNI のネイティブアプリケーションが JDK 共有ライブラリを検出できないことがあります。この問題は、LD_LIBRARY_PATH 環境変数に JDK のインストール先の jre/lib/sparc または jre/lig/i386 ディレクトリを含めることによって回避することができます。この問題は Solaris 7、Solaris 8 ソフトウェアでは発生しません。

シグナルの処理状態

JNI を使用するネイティブコードがシグナルの処理状態を変更してはなりません。VM はシグナルを使用します。シグナル処理に変更を加えると、VM で障害が発生することがあります。