目次 | 前へ | 次へ |
この章では、Java Native Interface (JNI) を紹介します。JNI は、ネイティブプログラミングインタフェースです。これによって、Java 仮想マシン (VM) で実行される Java コードが C、C++、アセンブリ言語などほかのプログラミング言語で書かれたアプリケーションやライブラリと相互運用できるようになります。
JNI のもっとも重要な利点は、これがベースとなる Java VM の実装に何の制限も課さないということです。そのため、Java VM ベンダーは VM のほかの部分に影響を与えずに、JNI のサポートを追加できます。プログラマは、1 つのバージョンのネイティブアプリケーションまたはライブラリを記述すれば、それが JNI をサポートするすべての Java VM 上で動作することを期待できます。
この章では次のトピックについて説明します。
Java でアプリケーション全体を記述できる一方で、Java だけではアプリケーションのニーズを満たせない状況もあります。Java でアプリケーション全体を記述できない場合、プログラマは JNI を使用して Java ネイティブメソッドを記述することにより、このような状況に対処できます。
次に、Java ネイティブメソッドを使用する必要のある場合をいくつか示します。
JNI を介して、プログラミングにネイティブメソッドを使用することにより、次のことが可能になります。
また、呼び出し API とともに JNI を使用することにより、任意のネイティブアプリケーションによる Java VM の埋め込みが可能になります。これにより、プログラマは VM ソースコードにリンクしなくても、既存のアプリケーションを Java 対応にできます。
現在、異なるベンダーの VM は異なるネイティブメソッドインタフェースを提供します。これらの異なるインタフェースによって、プログラマは与えられたプラットフォームで複数バージョンのネイティブメソッドライブラリを生成、維持、配布することが必要になります。
既存の代表的なネイティブメソッドインタフェースを次に紹介します。
JDK 1.0 には、ネイティブメソッドインタフェースが付属しています。残念ながら、2 つの大きな理由のため、このインタフェースはほかの Java VM には適用できません。
第一に、ネイティブコードは Java オブジェクトのフィールドに C 構造体のメンバーとしてアクセスします。ただし、Java 言語仕様では、オブジェクトをメモリーにどのように配置するかを定義していません。VM がオブジェクトをメモリーに異なったやり方で配置する場合、プログラマはネイティブメソッドライブラリを再コンパイルする必要があります。
第二に、JDK 1.0 のネイティブメソッドインタフェースは古典的なガベージコレクタに依存しています。たとえば、unhand
マクロを無制限に使用すると、ネイティブスタックの古典的な走査が必要になります。
Netscape(TM) は Java 仮想マシンで提供されるサービスの一般的なインタフェースである、Java Runtime Interface (JRI) を提案しました。JRI は移植性を考慮して設計されていますが、基盤となる Java VM の実装の詳細について十分に考慮されていません。JRI はネイティブメソッド、デバッギング、リフレクション、埋め込み (呼び出し) などを含めて、広範囲をサポートしています。
Microsoft Java VM は、2 つのネイティブメソッドインタフェースをサポートします。低レベルでは、効率的な Raw Native Interface (RNI) を提供します。RNI は、JDK のネイティブメソッドインタフェースとのソースレベルの高度な下位互換性を提供しますが、大きな違いが 1 つあります。厳格なガベージコレクションに依存する代わりに、ネイティブコードは RNI 機能を使用しガベージコレクタと明示的に相互動作しなければなりません。
これより高位のレベルでは、Microsoft の Java/COM インタフェースは、言語に依存しない標準バイナリインタフェースを Java VM に提供します。Java コードは COM オブジェクトを Java オブジェクトであるかのように使用できます。Java クラスもまた COM クラスとしてシステムの残りに開示できます。
充分検討された標準インタフェースには、次のような利点があります。
標準のネイティブメソッドインタフェースを確立する最善の方法は、Java VM に関心のあるすべての関係者を取り込むことです。このため、一様なネイティブメソッドインタフェースの設計について Java ライセンス保持者の間で一連の検討を行いました。それにより、標準のネイティブメソッドインタフェースは、次の要件を満たす必要があることが明らかになりました。
既存のアプローチの 1 つを標準インタフェースとして適用することは望ましいと思われます。これにより、異なる VM の複数のインタフェースを学ぶ必要があるプログラマにかける負荷は最低限になります。既存の解決策ではこの目標を完全に満足に達成するものは存在しませんでした。
Netscape の JRI は、移植性のあるネイティブメソッドインタフェースとして想定されるものにもっとも近く、設計の開始点として使用されてきました。JRI に慣れ親しんだユーザーは、API 命名規則、メソッドとフィールド ID の使用、ローカル参照とグローバル参照の使用などの類似性に気付くでしょう。しかし最善の努力にかかわらず、VM は JRI および JNI の両方をサポートできますが、JNI は JRI とバイナリ互換ではありません。
Microsoft の RNI は、ネイティブメソッドが古典的でないガベージコレクタと協同作業をする際の問題を解決しているため、JDK 1.0 を改善しているといえます。しかし、RNI は VM 非依存ネイティブメソッドインタフェースとしては適当ではありません。JDK のように、RNI ネイティブメソッドは Java オブジェクトに C 構造体としてアクセスします。このため次の 2 つの問題が発生します。
バイナリ標準として、COM は異なる VM 間で完全なバイナリ互換を保証します。COM メソッドの起動には間接的な呼び出しだけが必要で、この呼び出しはオーバーヘッドをほとんど伴いません。さらに、COM オブジェクトはバージョン問題の解決という点でダイナミックリンクライブラリに大きな改善をもたらします。
しかし、標準 Java ネイティブメソッドインタフェースとして COM を使用するには、次のいくつかの要因が問題になります。
Java オブジェクトを COM オブジェクトのようにネイティブコードに開示はしませんが、JNI インタフェース自身は COM とバイナリ互換です。COM が使用するものと同じジャンプテーブル構造体と呼び出し規則を使用します。これは、COM のクロスプラットフォームサポートが使用可能になると、JNI はただちに Java VM の COM インタフェースになれることを意味します。
JNI が、特定の Java VM がサポートする唯一のネイティブメソッドインタフェースであるべきだとは考えません。標準インタフェースは、ネイティブコードライブラリを異なる Java VM にロードしたいプログラマを支援します。あるケースでは、最高の効率を達成するために、プログラマは低レベルな VM 固有インタフェースを使用する必要があります。ほかのケースでは、プログラマは高レベルインタフェースを使用し、ソフトウェアコンポーネントを構築する可能性があります。実際、Java 環境とコンポーネントソフトウェア技術が円熟してくるにつれて、ネイティブメソッドがその重要性を徐々に失うことを望んでいます。
ネイティブメソッドプログラマは、JNI のプログラミングを開始する必要があります。JNI のプログラミングは、エンドユーザーが実行している可能性のあるベンダーの VM など未知のものから隔離してくれます。JNI 標準に準拠することで、ネイティブライブラリに対して、特定の Java VM で実行できる可能性が高くなります。たとえば、JDK 1.1 は JDK 1.0 で実装された古い型のネイティブメソッドインタフェースのサポートを継続しますが、JDK の将来バージョンでは古い型のネイティブメソッドインタフェースのサポートを中止することはたしかです。古い形式のインタフェースに依存するネイティブメソッドは書き直す必要があります。
Java VM を実装する場合には、JNI も実装する必要があります。Java Software および使用許諾者は、JNI がオブジェクト表現、ガベージコレクションスキームなどを含め、VM 実装にオーバーヘッドや制限を課さないように最善の努力をしています。我々が見落とした問題を発見した場合には、ご連絡下さい。
Java Runtime Environment (JRE) をよりよくサポートするために、JDK 1.1.2 では、呼び出し API の細かい点が拡張されました。これらの変更によって、既存のコードが使用できなくなることがありません。JNI ネイティブメソッドインタフェースは、変更されていません。
name=value
システムプロパティーを示す。この機能は、java コマンド行の -D オプションに相当する
目次 | 前へ | 次へ |