0Pricing
Java Academy · บทเรียน

เลย์เอาต์และโครงสร้าง

อธิบายเลย์เอาต์หน่วยความจำเนทีฟ

เลย์เอาต์และโครงสร้าง เป็นบทเรียน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เหตุใดจึงเลือก FFM แทน JNI
  2. MemorySegment และ Arena
  3. แฮนเดิลการเรียกลง
  4. เลย์เอาต์และโครงสร้าง
← กลับไปที่ Java Academy