MemorySegment と Arena
ヒープ外メモリを確保します。
「MemorySegment と Arena」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
オフヒープメモリ
FFMでは、ネイティブのオフヒープメモリを2つの中心的な型でモデル化します。MemorySegmentは連続したメモリ領域を表し、Arenaはそのライフタイムを管理します。
この2つを組み合わせることで、従来の安全でない手動バッファー管理を置き換えられます。
MemorySegmentとは
MemorySegmentは、メモリブロックを型付きで参照するウィンドウです。自身のサイズとライフタイムを把握しており、すべてのアクセスで境界チェックが行われます。
セグメントはオフヒープ(ネイティブ)にすることも、ヒープ上の配列をラップすることもできます。
Arenaとは
Arenaはセグメントを割り当て、セグメントが解放されるタイミングを定義します。Arenaを閉じると、そのArenaに属するすべてのセグメントが1回の決定的な処理で無効になります。
Arena.ofConfined():単一スレッドで使用し、明示的に閉じますArena.ofShared():複数スレッドからアクセスできますArena.global():解放されませんArena.ofAuto():GCによって解放されます
セグメントの割り当て
try-with-resourcesで制限付きArenaを使用するのが一般的なパターンです。バイト列を割り当てて使用し、closeするとすべてが解放されます。
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment seg = arena.allocate(16);
System.out.println("Allocated bytes: " + seg.byteSize());
}
System.out.println("Arena closed, memory freed");
}
}書き込みと読み取り
ValueLayoutとオフセットを受け取る型付きアクセサーを通じて、データを読み書きします。これにより、型安全でアラインメントに沿ったアクセスが可能になります。
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment seg = arena.allocate(ValueLayout.JAVA_INT);
seg.set(ValueLayout.JAVA_INT, 0, 42);
int value = seg.get(ValueLayout.JAVA_INT, 0);
System.out.println("Stored and read: " + value);
}
}
}型付きスロットの割り当て
生のバイト数を指定する代わりに、レイアウト単位で割り当てます。arena.allocate(JAVA_INT)は、1つのintに必要な、適切にアラインメントされたバイト数を正確に確保します。
これにより、サイズを手作業で計算する必要がなくなります。
値の配列
複数の要素を格納するには、シーケンスレイアウトを割り当てるか、要素数を渡します。インデックスアクセスでは、要素サイズに基づいて計算したオフセットを使用します。
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment ints = arena.allocate(ValueLayout.JAVA_INT, 5);
for (int i = 0; i < 5; i++) {
ints.setAtIndex(ValueLayout.JAVA_INT, i, i * 10);
}
System.out.println("Element 3: " + ints.getAtIndex(ValueLayout.JAVA_INT, 3));
}
}
}境界チェック
セグメントの範囲外を読み書きすると、IndexOutOfBoundsExceptionがスローされます。Arenaが閉じられた後にセグメントへアクセスすると、IllegalStateExceptionがスローされます。
このチェックがあるからこそ、JNIでは実現できなかったメモリ安全性をFFMで確保できます。
スレッド制約
制限付きArenaは、そのセグメントを作成したスレッドに結び付けます。別のスレッドがアクセスすると、WrongThreadExceptionがスローされます。
本当に共有するメモリにはArena.ofShared()を使用します。少しコストはかかりますが、複数スレッドからのアクセスが可能になります。
文字列の操作
FFMには、Java文字列とC文字列を橋渡しするヘルパーがあります。allocateUtf8String(新しい方式ではallocateFrom)はnull終端文字列を書き込み、getUtf8Stringは文字列を読み取ります。
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment cString = arena.allocateUtf8String("hello");
System.out.println("Read back: " + cString.getUtf8String(0));
}
}
}Arenaの選択
指針は次のとおりです。
- 短命で単一スレッドのバッファー:
ofConfined() - スレッド間で共有する場合:
ofShared() - ライフタイムをGCに管理させる場合:
ofAuto() - プロセス全体で使う定数:
global()
確認問題
ネイティブメモリが解放されるタイミングを決めるものを思い出してください。
まとめ
オフヒープメモリの管理方法を学びました。
MemorySegment:境界チェックされるメモリ領域Arena:ライフタイムを管理します(制限付き、共有、自動、グローバル)ValueLayoutとget/set、getAtIndexによる型付きアクセス- 境界チェックとスレッド制約による安全性
次は、ダウンコールハンドルを使ってネイティブ関数を呼び出します。
よくある質問
「MemorySegment と Arena」レッスンは無料ですか?
はい。「MemorySegment と Arena」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「MemorySegment と Arena」で何を学びますか?
ヒープ外メモリを確保します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「MemorySegment と Arena」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- JNI より FFM を使う理由
- MemorySegment と Arena
- ダウンコールハンドル
- レイアウトと構造体