JDK強化提案 (JEP) 191は、Java他言語関数インターフェース (FFI)を定義する。FFIは、ネイティブ関数をJavaのメソッドにバインドしたり、ネイティブメモリのブロックを管理したりできるインターフェースだ。このJEPは、JDKに新しいネイティブレベルの機能を追加しやすくしたり、Java開発で使う標準FFIを提供できるようにしたりする。Javaネイティブインターフェース (JNI) は、Javaのネイティブコードを書くための、現在の標準プログラミングインターフェースだ。JNIではネイティブ関数を簡単に作れないため、Java Native Access (JNA) や Java Native Runtime (JNR)などのライブラリが作り出された。JNAとJNRはJNI上にあり、JEP 191はJNRベースになるだろう。
JEP 191により、JNAやJNRと同様、他言語関数インターフェースはJavaレベルで提供される。そのため、JVMレベルでネイティブメモリを管理し、ネイティブ関数へ簡単にアクセスできるようになる。また、標準Java FFIの将来のJSRもサポートする。Java FFI APIは、NIOのようにネイティブコードを動かす機能や高度なファイルシステムメタデータ、プロセス管理を実装するのに使われる。FFI APIは、JNIよりも、ネイティブコードとメモリをバインドするのに向いているだろう。JEP 191はJNIへの拡張を含んでいないが、それらの拡張はJSRプロセスに入れられるかもしれない。
JNIは現在の標準プログラミングインターフェースであり、Javaネイティブメソッドを書いたり、ネイティブアプリケーションにJavaバーチャルマシンを組み込んだりする。また、JVMと管理されていないネイティブ環境の間の境界を制御し、データマーシャリングやオブジェクトライフサイクル管理のためのプロトコルを提供する。JEP 191によると、JNIのこれらの機能は、開発者にとって、もっとも骨が折れることだ。
- 開発者たちにCのコードを書くように要求すれば、開発者たちはJavaとはまったく違う世界の専門技術を持たなければならない。
- JNIを使うには、普通は、典型的なCやJava開発者たちにはない専門技術が必要だ。開発者はJVMがメモリとコードをどのように管理するか、少なくとも、ある程度の知識がなければならない。
- 開発者たちは、エンドユーザが同じことをできる適切なツールをサポートしたり、提供したりするプラットォームにあわせて、コードをビルドできなければならない。
- JNIベースのライブラリは、ネイティブアプリケーションにバインドされた同様のライブラリと比べて、通常はパフォーマンスが悪い。
- JNIは、セキュリティ上は分かりにくい境界となる。ライブラリのファンクションがどの呼び出しを使うのかということや、ライブラリのコードがJVMの安定性やセキュリティを脅かすかどうかということは、JDKからは認識できない。
JNIの難しさは、JDKのビルトインFFI APIで扱える。Java FFIは実装がより簡単で、JVM内部や様々なホストプラットォームに関する専門知識をそれほど必要としない。FFI APIは、以下の機能を提供する。
- ネイティブライブラリの呼び出しやネイティブメモリ構造を記述するためのメタデータシステム
- ネイティブライブラリを見つけて、ロードする仕組み
- メタデータに基づき、ライブラリ/ファンクションやJavaエンドポイントへのメモリ構造をバインドする仕組み
- Javaデータ型をネイティブデータ型にマーシャリング/アンマーシャリングするコード
Java FFIが必要になったのは、JNAやJNRライブラリを使うためであり、JNAライブラリは幅広く使われる。JNRライブラリは、さらに広範囲にわたるもので、様々なレベルの抽象化を実装し、ファンクションやメモリメタデータを提供する。また、ライブラリとファンクションのバインディングを取り除く。JNRはJRubyプロジェクトでよく使われており、JEP 191の基礎を作るものになるだろう。