目次 | 前の項目 | 次の項目 Java Native Interface 仕様


1 - 入門


この章では、Java Native Interface (JNI) を紹介します。JNI は、ネイティブプログラミングインタフェースです。これによって、Java 仮想マシン* (VM) で実行される Java コードが C、C++、アセンブリ言語など他のプログラミング言語で書かれたアプリケーションやライブラリと相互運用できるようになります。

JNI のもっとも重要な利点は、これが基礎となる Java VM の実装に何の制限も課さないということです。そのため、Java VM ベンダーは VM の他の部分に影響を与えずに、JNI のサポートを追加できます。プログラマは、1 つのバージョンのネイティブアプリケーションまたはライブラリを記述すれば、それが JNI をサポートするすべての Java VM 上で動作することを期待できます。

この章では以下について説明します。


Java Native Interface の概要

Java でアプリケーション全体を記述することができる一方で、Java だけではアプリケーションのニーズを満たせない状況もあります。Java でアプリケーション全体を記述できない場合、プログラマは JNI を使用して、「Java ネイティブメソッド」を記述することにより、このような状況に対処できます。

以下に、Java ネイティブメソッドを使用する必要のある場合をいくつか示します。

JNI を介して、プログラミングにネイティブメソッドを使用することにより、以下のことが可能になります。

また、「呼び出し API」とともに JNI を使用することにより、任意のネイティブアプリケーションによる Java VM の埋め込みが可能になります。これにより、プログラマは VM ソースコードにリンクしなくても、既存のアプリケーションを Java 対応にできます。


背景

現在、異なるベンダーの VM は異なるネイティブメソッドインタフェースを提供します。これらの異なるインタフェースによって、プログラマは与えられたプラットフォームで複数バージョンのネイティブメソッドライブラリを生成、維持、配布することが必要になります。

既存の代表的なネイティブメソッドインタフェースを以下に紹介します。


JDK 1.0 ネイティブメソッドインタフェース

JDK 1.0 は、ネイティブメソッドインタフェースを添付して出荷されました。残念ながら、2 つの大きな理由のため、このインタフェースは他の Java VM には適用できません。

第一に、ネイティブコードは Java オブジェクトのフィールドに C 構造体のメンバとしてアクセスします。ただし、Java 言語仕様では、オブジェクトをメモリにどのように配置するかを定義していません。VM がオブジェクトをメモリに異ったやり方で配置する場合、プログラマはネイティブメソッドライブラリを再コンパイルする必要があります。

第ニに、JDK 1.0 のネイティブメソッドインタフェースは古典的なガベージコレクタに依存しています。たとえば、unhand マクロを無制限に使用すると、ネイティブスタックの古典的な走査が必要になります。


Java Runtime Interface

NetscapeTM は Java 仮想マシンで提供されるサービスの一般的なインタフェースである、Java Runtime Interface (JRI) を提案しました。JRI は移植性を考慮して設計されていますが、基盤となる Java VM の実装の詳細について十分に考慮されていません。JRI はネイティブメソッド、デバッギング、リフレクション、埋め込み (呼び出し) などを含めて、広範囲をサポートしています。


Raw Native Interface および Java/COM インタフェース

Microsoft Java VM は、2 つのネイティブメソッドインタフェースをサポートします。低レベルでは、効率的な Raw Native Interface (RNI) を提供します。JDK のネイティブメソッドインタフェースとのソースレベルの高度の下位互換性を提供しますが、RNI には大きな違いが 1 つあります。厳格なガベージコレクションに依存する代わりに、ネイティブコードは RNI 機能を使用しガベージコレクタと明示的に相互動作しなければなりません。

高レベルでは、Microsoft の Java/COM インタフェースは Java VM に対して言語独立の標準バイナリインタフェースを提供します。Java コードは COM オブジェクトを Java オブジェクトであるかのように使用できます。Java クラスもまた COM クラスとしてシステムの残りに開示することができます。


目的

充分検討された標準インタフェースには、次のような利点があります。

標準のネイティブメソッドインタフェースを確立する最善の方法は、Java VM に関心のあるすべての関係者を取り込むことです。このため、一様なネイティブメソッドインタフェースの設計について Java ライセンス保持者の間で一連の検討を行いました。それにより、標準のネイティブメソッドインタフェースは、次の要件を満たす必要があることが明らかになりました。


Java Native Interface のアプローチ

既存のアプローチの 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 のプログラミングを開始する必要があります。JNI のプログラミングは、エンドユーザが実行している可能性のあるベンダーの VM など未知のものから隔離してくれます。JNI 標準に準拠することで、ネイティブライブラリに対して、特定の Java VM で実行できる可能性が高くなります。たとえば、JDK 1.1 は JDK 1.0 で実装された古い型のネイティブメソッドインタフェースのサポートを継続しますが、JDK の将来バージョンでは古い型のネイティブメソッドインタフェースのサポートを中止することは確かです。古い形式のインタフェースに依存するネイティブメソッドは書き直す必要があります。

Java VM を実装する場合には、JNI も実装する必要があります。Java ソフトウェアおよび使用許諾者は、JNI がオブジェクト表現、ガベージコレクション方式などを含め、VM 実装にオーバーヘッドや制限を課さないように最善の努力をしています。我々が見落とした問題を発見した場合には、ご連絡ください。


JDK 1.1.2 での変更点

Java Runtime Environment (JRE) をよりよくサポートするために、JDK 1.1.2 では、呼び出し API の細かい点が拡張されました。これらの変更によって、既存のコードが使用できなくなることがありません。JNI ネイティブメソッドインタフェースは、変更されていません。

* この Web サイトで使用されている用語「Java 仮想マシン」または「JVM」は、Java プラットフォーム用の仮想マシンを表します。


目次 | 前の項目 | 次の項目

Java Native Interface 仕様 (1997 年 3 月 15 日に dkramer によって生成された HTML)
Copyright © 1996, 1997 Sun Microsystems, Inc.All rights reserved
コメントや訂正は、jni@java.sun.com までお送りください。