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

MemorySegment และ Arena

จัดสรรหน่วยความจำนอกฮีป

MemorySegment และ Arena เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

หน่วยความจำนอกฮีป

FFM จำลองหน่วยความจำเนทีฟนอกฮีปด้วยชนิดข้อมูลหลักสองชนิด: MemorySegment แทนบริเวณหน่วยความจำต่อเนื่อง และ Arena ควบคุมอายุการใช้งานของบริเวณนั้น

ทั้งสองชนิดนี้ใช้แทนการจัดการบัฟเฟอร์ด้วยตนเองที่ไม่ปลอดภัยในอดีต

MemorySegment คืออะไร

MemorySegment คือหน้าต่างที่มีชนิดข้อมูลกำกับอยู่เหนือบล็อกหน่วยความจำ โดยทราบ ขนาด และ อายุการใช้งาน ของตนเอง และตรวจสอบขอบเขตในการเข้าถึงทุกครั้ง

เซกเมนต์อาจอยู่นอกฮีป (เป็นหน่วยความจำเนทีฟ) หรือห่อหุ้มอาร์เรย์บนฮีปก็ได้

Arena คืออะไร

Arena จัดสรรเซกเมนต์และกำหนดเวลาที่เซกเมนต์เหล่านั้นจะถูกคืนหน่วยความจำ เมื่อปิดอารีนา เซกเมนต์ทั้งหมดจะใช้งานไม่ได้ในขั้นตอนที่กำหนดแน่นอนเพียงครั้งเดียว

  • Arena.ofConfined(): ใช้กับเธรดเดียวและปิดอย่างชัดเจน
  • Arena.ofShared(): เข้าถึงได้จากหลายเธรด
  • Arena.global(): ไม่ถูกคืนหน่วยความจำ
  • Arena.ofAuto(): ตัวเก็บขยะเป็นผู้คืนหน่วยความจำ

การจัดสรรเซกเมนต์

การใช้อารีนาแบบจำกัดการเข้าถึงภายในโครงสร้างจัดการทรัพยากรอัตโนมัติเป็นรูปแบบที่ใช้กันทั่วไป จัดสรรไบต์ ใช้งาน แล้วปิดเพื่อคืนหน่วยความจำทั้งหมด

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) จะจองไบต์ที่มีขนาดพอดีและจัดแนวถูกต้องสำหรับค่า 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 การเข้าถึงเซกเมนต์หลังจากปิดอารีนาจะทำให้เกิด IllegalStateException

การตรวจสอบเหล่านี้ทำให้หน่วยความจำของ FFM ปลอดภัย ขณะที่ JNI ไม่มีคุณสมบัตินี้

การจำกัดการเข้าถึง

อารีนาแบบจำกัดการเข้าถึงจะผูกเซกเมนต์ของตนไว้กับเธรดที่สร้างเซกเมนต์เหล่านั้น หากเธรดอื่นเข้าถึงเซกเมนต์ จะทำให้เกิด WrongThreadException

สำหรับหน่วยความจำที่ต้องใช้ร่วมกันจริง ๆ ให้ใช้ Arena.ofShared() ซึ่งอนุญาตการเข้าถึงจากหลายเธรดโดยมีต้นทุนเพิ่มขึ้นเล็กน้อย

การทำงานกับสตริง

FFM มีตัวช่วยสำหรับเชื่อมสตริง Java กับสตริงภาษาซี 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()
  • ให้ตัวเก็บขยะจัดการอายุการใช้งาน: ofAuto()
  • ค่าคงที่ตลอดทั้งกระบวนการ: global()

ตรวจสอบอย่างรวดเร็ว

ทบทวนว่าอะไรเป็นตัวกำหนดเวลาที่หน่วยความจำเนทีฟจะถูกคืน

สรุปทบทวน

คุณได้เรียนรู้การจัดการหน่วยความจำนอกฮีป:

  • MemorySegment: บริเวณหน่วยความจำที่ตรวจสอบขอบเขต
  • Arena: ควบคุมอายุการใช้งาน (แบบจำกัดการเข้าถึง แบบใช้ร่วมกัน แบบอัตโนมัติ และแบบส่วนกลาง)
  • การเข้าถึงแบบมีชนิดข้อมูลผ่าน ValueLayout ด้วย get/set และ getAtIndex
  • ความปลอดภัยจากการตรวจสอบขอบเขตและการจำกัดการเข้าถึง

ถัดไป: การเรียกใช้ฟังก์ชันเนทีฟด้วยตัวจัดการการเรียกลง

คำถามที่พบบ่อย

บทเรียน “MemorySegment และ Arena” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “MemorySegment และ Arena” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “MemorySegment และ Arena”

จัดสรรหน่วยความจำนอกฮีป คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “MemorySegment และ Arena” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม

ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

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

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