เลย์เอาต์และโครงสร้าง
อธิบายเลย์เอาต์หน่วยความจำเนทีฟ
เลย์เอาต์และโครงสร้าง เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
การอธิบายหน่วยความจำเนทีฟ
ข้อมูลเนทีฟแทบไม่เคยเป็นเพียงค่าเดียว ภาษาซีใช้โครงสร้างข้อมูล อาร์เรย์ และยูเนียน FFM จำลองรูปแบบเหล่านี้ด้วย เลย์เอาต์หน่วยความจำ ทำให้คุณอ่านและเขียนหน่วยความจำเนทีฟที่มีโครงสร้างได้อย่างปลอดภัย
ตระกูลเลย์เอาต์
ชนิดของเลย์เอาต์มีลำดับชั้นขนาดเล็กดังนี้:
ValueLayout: ชนิดพื้นฐาน (จำนวนเต็ม จำนวนเต็มขนาดยาว จำนวนทศนิยมสองเท่า ที่อยู่)SequenceLayout: อาร์เรย์ขนาดคงที่ของเลย์เอาต์หนึ่งชนิดStructLayout: ฟิลด์ที่วางเรียงตามลำดับUnionLayout: ฟิลด์ที่ใช้พื้นที่ทับซ้อนกัน
เลย์เอาต์ค่า
เลย์เอาต์ที่เรียบง่ายที่สุดคือเลย์เอาต์ค่าที่มีมาให้ เลย์เอาต์เหล่านี้เก็บข้อมูลขนาด การจัดแนว และลำดับไบต์ไว้
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(...) โดยตั้งชื่อให้แต่ละฟิลด์ด้วย withName พิจารณา 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 จากนิพจน์เส้นทาง 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);
}
}การอ่านและเขียนโครงสร้างข้อมูล
จัดสรรเซกเมนต์ให้มีขนาดตามเลย์เอาต์ แล้วใช้ตัวจัดการตัวแปรเพื่อกำหนดค่าและอ่านค่าฟิลด์ วิธีนี้จำลองการเติมข้อมูลลงในโครงสร้างข้อมูลของภาษาซี
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) + ")");
}
}
}ช่องว่างเติมและการจัดแนว
คอมไพเลอร์ภาษาซีจะแทรก ช่องว่างเติม เพื่อให้ฟิลด์จัดแนวอย่างถูกต้อง FFM ไม่เพิ่มช่องว่างนี้ให้โดยอัตโนมัติ ดังนั้นคุณต้องใส่ MemoryLayout.paddingLayout(n) เพื่อให้ตรงกับเลย์เอาต์ของภาษาซีอย่างสมบูรณ์
หากจัดแนวผิด ฟิลด์ทุกฟิลด์หลังช่องว่างจะเสียหาย
ตัวอย่างการเพิ่มช่องว่างอย่างชัดเจน
สำหรับ struct { char c; int n; } ค่า int ต้องจัดแนวกับขอบเขต 4 ไบต์ จึงต้องมีไบต์เติม 3 ไบต์ตามหลัง char
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) จำลองตัวอย่างเช่นอาร์เรย์ของค่า double จำนวน 10 ค่า
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) ใช้นำทางไปยังข้อมูลที่ซ้อนกันในระดับลึก
วิธีนี้รองรับโครงสร้างข้อมูลของภาษาซีในโลกจริงที่มีความซับซ้อนได้ทุกรูปแบบ
ออฟเซ็ตและการตัดแบ่ง
คุณสามารถสอบถาม byteOffset ของฟิลด์จากเส้นทางของฟิลด์ และใช้ segment.asSlice(offset, size) เพื่อรับเซกเมนต์ย่อย ซึ่งมีประโยชน์เมื่อต้องส่งฟิลด์หนึ่งของโครงสร้างข้อมูลไปยังฟังก์ชันเนทีฟ
ตรวจสอบอย่างรวดเร็ว
ทบทวนข้อผิดพลาดที่มักเกิดขึ้นกับโครงสร้างข้อมูล
สรุปทบทวน
คุณได้เรียนรู้การอธิบายข้อมูลเนทีฟ:
- ตระกูลเลย์เอาต์:
ValueLayout,SequenceLayout,StructLayout,UnionLayout - ตั้งชื่อฟิลด์ด้วย
withNameและเข้าถึงผ่านVarHandleกับองค์ประกอบเส้นทาง - เพิ่ม
paddingLayoutอย่างชัดเจนเพื่อการจัดแนวที่ถูกต้อง - ประกอบเลย์เอาต์ที่ซ้อนกันและตัดแบ่งด้วย
asSlice
หลักสูตรส่วนติดต่อฟังก์ชันและหน่วยความจำภายนอกจบลงเพียงเท่านี้
คำถามที่พบบ่อย
บทเรียน “เลย์เอาต์และโครงสร้าง” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “เลย์เอาต์และโครงสร้าง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “เลย์เอาต์และโครงสร้าง”
อธิบายเลย์เอาต์หน่วยความจำเนทีฟ คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “เลย์เอาต์และโครงสร้าง” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เหตุใดจึงเลือก FFM แทน JNI
- MemorySegment และ Arena
- แฮนเดิลการเรียกลง
- เลย์เอาต์และโครงสร้าง