import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;

public class MemoriLuar {

    public static void main(String[] args) {
        // Arena confined: satu pemilik thread, ditutup otomatis oleh try.
        try (Arena arena = Arena.ofConfined()) {
            // Alokasi off-heap: 4 slot int (16 byte) di luar heap JVM.
            MemorySegment seg = arena.allocate(ValueLayout.JAVA_INT, 4);

            seg.set(ValueLayout.JAVA_INT, 0L, 100);
            seg.set(ValueLayout.JAVA_INT, 4L, 200);
            seg.set(ValueLayout.JAVA_INT, 8L, 300);
            seg.set(ValueLayout.JAVA_INT, 12L, 400);

            long jumlah = 0;
            for (long ofset = 0; ofset < seg.byteSize(); ofset += 4) {
                jumlah += seg.get(ValueLayout.JAVA_INT, ofset);
            }
            System.out.println("ukuran segmen : " + seg.byteSize() + " byte");
            System.out.println("jumlah nilai  : " + jumlah);

            // allocateFrom menyalin array Java ke memori luar sekaligus.
            MemorySegment salinan = arena.allocateFrom(
                    ValueLayout.JAVA_INT, new int[]{7, 8, 9});
            System.out.println("salinan[2]    : " + salinan.get(ValueLayout.JAVA_INT, 8L));
        } // arena.close() di sini: seluruh segmen dilepas sekaligus

        // Segmen dari arena tertutup menolak akses dengan exception jelas.
        MemorySegment seg = null;
        try (Arena arena = Arena.ofConfined()) {
            seg = arena.allocate(ValueLayout.JAVA_INT, 1);
        }
        try {
            seg.get(ValueLayout.JAVA_INT, 0L);
        } catch (IllegalStateException e) {
            System.out.println("setelah close : " + e.getClass().getSimpleName()
                    + " (" + e.getMessage() + ")");
        }
    }
}
