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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เหตุใดจึงเลือก FFM แทน JNI
- MemorySegment และ Arena
- แฮนเดิลการเรียกลง
- เลย์เอาต์และโครงสร้าง