レイアウトと構造体
ネイティブメモリのレイアウトを記述します。
「レイアウトと構造体」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
ネイティブメモリの記述
ネイティブデータが単一の値だけであることはほとんどありません。Cでは構造体、配列、共用体を使用します。FFMでは、これらの形状をメモリレイアウトでモデル化し、構造化されたネイティブメモリを安全に読み書きできます。
レイアウトの種類
レイアウト型は小さな階層を形成しています。
ValueLayout:プリミティブ(int、long、double、アドレス)SequenceLayout:レイアウトの固定長配列StructLayout:フィールドを順番に配置したものUnionLayout:フィールドが重なっているもの
ValueLayout
最も単純なレイアウトは、組み込みの値レイアウトです。サイズ、アラインメント、バイト順を保持しています。
import java.lang.foreign.ValueLayout;
public class Main {
public static void main(String[] args) {
System.out.println("int size: " + ValueLayout.JAVA_INT.byteSize());
System.out.println("double size: " + ValueLayout.JAVA_DOUBLE.byteSize());
}
}構造体の定義
MemoryLayout.structLayout(...)を使ってCの構造体をモデル化し、各フィールドにwithNameで名前を付けます。Cのstruct Point { int x; int y; }を考えてみましょう。
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
StructLayout point = MemoryLayout.structLayout(
ValueLayout.JAVA_INT.withName("x"),
ValueLayout.JAVA_INT.withName("y"));
System.out.println("Point size: " + point.byteSize());
}
}フィールド用のVarHandle
名前付きフィールドを読み書きするには、パス式を使ってVarHandleを導出します。groupElement("x")は名前でフィールドを選択します。
import java.lang.foreign.*;
import java.lang.invoke.VarHandle;
public class Main {
public static void main(String[] args) {
StructLayout point = MemoryLayout.structLayout(
ValueLayout.JAVA_INT.withName("x"),
ValueLayout.JAVA_INT.withName("y"));
VarHandle xHandle = point.varHandle(
MemoryLayout.PathElement.groupElement("x"));
System.out.println("Built VarHandle for x: " + xHandle);
}
}構造体の読み書き
レイアウトに合わせたサイズのセグメントを割り当て、var handleを使ってフィールドの設定と取得を行います。これはCの構造体に値を格納する処理に相当します。
import java.lang.foreign.*;
import java.lang.invoke.VarHandle;
public class Main {
public static void main(String[] args) {
StructLayout point = MemoryLayout.structLayout(
ValueLayout.JAVA_INT.withName("x"),
ValueLayout.JAVA_INT.withName("y"));
VarHandle xh = point.varHandle(MemoryLayout.PathElement.groupElement("x"));
VarHandle yh = point.varHandle(MemoryLayout.PathElement.groupElement("y"));
try (Arena arena = Arena.ofConfined()) {
MemorySegment p = arena.allocate(point);
xh.set(p, 0L, 3);
yh.set(p, 0L, 4);
System.out.println("Point = (" + xh.get(p, 0L) + ", " + yh.get(p, 0L) + ")");
}
}
}パディングとアラインメント
Cコンパイラーは、フィールドをアラインメントに合わせるためにパディングを挿入します。FFMはこれを自動的には追加しないため、Cのレイアウトと完全に一致させるにはMemoryLayout.paddingLayout(n)を含める必要があります。
アラインメントを間違えると、隙間の後にあるすべてのフィールドが破損します。
明示的なパディングの例
struct { char c; int n; }では、intを4バイト境界に合わせる必要があるため、charの後に3バイトのパディングが入ります。
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
StructLayout s = MemoryLayout.structLayout(
ValueLayout.JAVA_BYTE.withName("c"),
MemoryLayout.paddingLayout(3),
ValueLayout.JAVA_INT.withName("n"));
System.out.println("Aligned struct size: " + s.byteSize());
}
}シーケンスレイアウト
SequenceLayoutは配列を記述します。MemoryLayout.sequenceLayout(count, element)を使うと、たとえば10個のdoubleの配列をモデル化できます。
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
SequenceLayout arr = MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_DOUBLE);
System.out.println("Array bytes: " + arr.byteSize());
}
}入れ子になったレイアウト
レイアウトは組み合わせて使えます。構造体にシーケンスを含めたり、シーケンスに構造体を含めたりできます。sequenceElement()やgroupElement(name)のようなパス式で、入れ子になったデータの深い位置まで移動できます。
これにより、現実の複雑なCデータ構造にも対応できます。
オフセットとスライス
パスからフィールドのbyteOffsetを取得し、segment.asSlice(offset, size)を使ってサブセグメントを取得できます。これは、構造体の1つのフィールドをネイティブ関数に渡す場合に便利です。
確認問題
構造体でよくある落とし穴を思い出してください。
まとめ
ネイティブデータの記述方法を学びました。
- レイアウトの種類:
ValueLayout、SequenceLayout、StructLayout、UnionLayout withNameでフィールドに名前を付け、VarHandleとパス要素でアクセスします- 正しいアラインメントのために
paddingLayoutを明示的に追加します - 入れ子になったレイアウトを組み合わせ、
asSliceでスライスします
これでForeign Function and Memory APIのコースは完了です。
よくある質問
「レイアウトと構造体」レッスンは無料ですか?
はい。「レイアウトと構造体」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「レイアウトと構造体」で何を学びますか?
ネイティブメモリのレイアウトを記述します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「レイアウトと構造体」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。