- JNIは、JVMコードがネイティブのCまたはC++関数を呼び出したり、ネイティブコードがJavaにコールバックしたりできるようにする、組み込みのインターフェースです。
nativeメソッドにはJavaの本体がなく、JVMは実行時にコンパイルされた関数にリンクします。- プログラムは、ネイティブライブラリの再利用、OSへのアクセス、ホットパスの高速化、またはハードウェアの操作などに使用します。
- 境界は明確です。ネイティブのクラッシュはJVMをダウンさせることができ、ネイティブのビルドはプラットフォーム固有です.
JNIは、Java Native Interfaceのことで、Javaに組み込まれている機能であり、JVM上で実行されているコードがCまたはC++で記述された関数を呼び出したり、そのネイティブコードがJavaに呼び出しを戻したりすることを可能にします。JavaプログラムがJVMの外にアクセスしてプラットフォームライブラリやコンパイルされた機械語を使用するための手段です.
JNI が行うこと
JNI は、2 つの世界を繋ぎます。JVM 上で実行される管理された Java コードと、機械語命令にコンパイルされたネイティブコードです。Java メソッドは native とマークされ、Java では本体を持っていません。実行時に JVM はネイティブライブラリをロードし、そのメソッドを対応する C または C++ 関数にリンクします。そこから、両側のコードが引数と戻り値を相互に渡します。
ネイティブ側は JNIEnv ポインタを受け取ります。そのハンドルはゲートウェイであり、Java フィールドの読み取り、Java メソッドの呼び出し、オブジェクトの作成、例外の発生のための関数を公開します。したがって、ブリッジは一方通行ではなく、双方向で動作します。
プログラムがそれを使用する理由
ほとんどの Java コードは JNI を必要としません。プログラムが使用するのは、いくつかの状況に限られます。
- 既存のネイティブコードの再利用: 成熟した C または C++ ライブラリがすでにその役割を果たしており、Java で書き直す価値がない場合。
- オペレーティングシステムへのアクセス: プラットフォームの機能の中には、純粋な Java API がないものがあり、ネイティブ呼び出しが唯一の方法です。
- ホットパスの高速化: 密な数値計算や低レベルのルーチンは、JVM 上で実行するよりもコンパイルされたネイティブコードとして高速に実行できる場合があります。
- ハードウェアやドライバへのアクセス: グラフィックス、オーディオ、デバイスアクセスは、多くの場合、ネイティブライブラリの背後に存在します。
JNI 呼び出しの仕組み
手順はあらゆるプラットフォームで同じです.
| ステップ | 発生する内容 |
|---|---|
| 宣言 | native キーワードが付与され、本体を持たない Java メソッドが記述されます。 |
| 構築 | C または C++ 関数が共有ライブラリ (.dll, .so, .dylib) にコンパイルされます。 |
| 読み込み | Java が実行時に System.loadLibrary を呼び出してそのライブラリをロードします。 |
| リンク | JVM が native メソッドと C 関数を名前で照合します。 |
| 呼び出し | Java がメソッドを呼び出し、制御がネイティブコードに渡り、戻ります。 |
関数名は JVM が見つけられるように固定されたパターンに従っており、生成されたヘッダーには実装すべき正確なシグネチャが示されています。
コストとリスク
JNI は強力ですが、危険な側面もあります。ネイティブコードのクラッシュは、JVM 全体をダウンさせる可能性があります。なぜなら、そのコードは JVM の安全網の外で実行されるからです。ネイティブ側で割り当てられたメモリはガベージコレクションされないため、メモリリークが発生しやすくなります。Java とネイティブ間のクロスオーバーにはオーバーヘッドがあるため、タイトなループで境界を越えて呼び出すと遅くなる可能性があります。そして、ネイティブライブラリはプラットフォーム固有です。Windows 用にビルドされたものは、別のコンパイルなしで Linux 上では実行できません.
少しだけ使ってください
よくある質問
はい。JNI は JDK と JVM に同梱されています。Java 側で追加のインストールは不要ですが、C または C++ の部分をコンパイルするためには、ネイティブツールチェーンが必要です。
いいえ。Java側のコードは引き続き移植可能ですが、ネイティブライブラリは特定のオペレーティングシステムとCPU向けにコンパイルされるため、プラットフォームごとに個別のネイティブビルドを配布することになります。
いいえ、それが最初から組み込まれている標準的な方法です。新しいJavaバージョンでは、より安全で使いやすい外国関数インターフェース(FFI)が追加されましたが、JNIは依然として広く使用されており、よく理解されています。
Javaで記述されたクライアントは、JVMでは直接実行できないことがあるため、ネイティブライブラリが必要となる場合があります。JNIはそのライブラリをロードし、呼び出すための標準的なインターフェースです。