JNI より FFM を使う理由
より安全にネイティブ連携します。
「JNI より FFM を使う理由」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
ネイティブコードの呼び出し
Javaでは、Cライブラリを呼び出したり、ヒープ外メモリを扱ったりする必要が生じることがあります。従来の方法はJava Native Interface(JNI)でした。現在の方法は、Java 22(JEP 454)で正式採用されたForeign Function and Memory API(FFM)です。
このレッスンでは、FFMを選ぶほうがよい理由を説明します。
JNIで必要だったこと
JNIには多くの手間がかかりました。
- 扱いにくい
JNIEXPORTシグネチャでCの接着コードを書く - プラットフォームごとにネイティブ共有ライブラリをコンパイルする
- Java型とC型の間で手動変換する
- ミスによってJVMを簡単にクラッシュさせてしまう
FFMは純粋なJava
FFMを使うと、Javaだけでネイティブ関数の呼び出しとネイティブメモリへのアクセスを行えます。Cの接着コードも、別のコンパイル手順も、手書きのマーシャリングも必要ありません。
ネイティブ関数のシグネチャをJavaで記述し、メソッドハンドルを通じて呼び出します。
主要なパッケージ
すべての機能はjava.lang.foreignにあります。主な型は次のとおりです。
- 関数の検索とバインドに使う
LinkerとSymbolLookup - ネイティブメモリ用の
MemorySegment - 決定的なライフタイム管理用の
Arena - メモリや関数の形状を記述する
MemoryLayoutとFunctionDescriptor
設計による安全性
FFMはJNIよりもはるかに安全です。
- メモリアクセスが境界チェックされます
Arenaにライフタイムが結び付いているため、解放済みメモリへのアクセスが検出されます- スレッド制約により、安全でないスレッド間アクセスが防止されます
誤りが発生しても、VMがクラッシュするのではなくJava例外がスローされます。
APIを少し体験する
このコード例では、Cのstrlen関数を検索し、その関数へのハンドルを準備します。重要なのは、これがすべて通常のJavaコードだという点です。
import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
public class Main {
public static void main(String[] args) {
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle strlen = linker.downcallHandle(
stdlib.find("strlen").orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS));
System.out.println("Bound a handle to strlen: " + strlen);
}
}パフォーマンス
FFMのダウンコールはJNIと同等の性能を発揮し、多くの場合はそれより高速です。JITが生成されたスタブをインライン化して最適化できるためです。呼び出しごとに越えるCのトランポリンもありません。
ネイティブアクセスの有効化
ネイティブコードは危険な場合があるため、FFMでは警告が表示されたり、オプトインが必要になったりすることがあります。起動時に--enable-native-access=ALL-UNNAMED(または特定のモジュール名)を指定してアクセスを許可すると、警告を抑制できます。
sun.misc.Unsafeの置き換え
FFM(Memory APIと組み合わせたもの)は、長らく非推奨となっているsun.misc.Unsafeのオフヒープ操作に対する、正式にサポートされた代替手段でもあります。ネイティブバッファーを手動で管理していたライブラリは、安全でサポート対象のAPIへ移行できます。
ツール:jextract
大規模なCライブラリでは、付属ツールのjextractがCヘッダーファイルを読み取り、JavaのFFMバインディングを自動生成します。ディスクリプターを手作業で記述する必要がなくなります。
これはコードジェネレーターに近い、FFMの生産性を高めるツールです。
FFMを使う場面
次のような場合はFFMを使用します。
- 既存のC/C++ライブラリを呼び出す場合
- OSと低レベルで相互運用する場合
- 大きなオフヒープバッファーを効率的に管理する場合
純粋なJavaの処理では、FFMは必要ありません。
確認問題
JNIに対する主な利点を思い出してください。
まとめ
FFMがJNIより優れている理由を学びました。
- 純粋なJavaで動作し、Cの接着コードや追加のコンパイルが不要です
- 境界チェック、Arenaのライフタイム、スレッド制約によって安全です
- 同等以上のパフォーマンスを発揮します
sun.misc.Unsafeを置き換え、jextractと組み合わせて使えます
次は、MemorySegmentとArenaを使ったネイティブメモリの管理です。
よくある質問
「JNI より FFM を使う理由」レッスンは無料ですか?
はい。「JNI より FFM を使う理由」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「JNI より FFM を使う理由」で何を学びますか?
より安全にネイティブ連携します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「JNI より FFM を使う理由」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- JNI より FFM を使う理由
- MemorySegment と Arena
- ダウンコールハンドル
- レイアウトと構造体