0Pricing
Java Academy · Lesson

MemorySegment and Arena

Allocate off-heap memory.

MemorySegment and Arena is a free Java Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Off-Heap Memory

FFM models native, off-heap memory with two central types: MemorySegment represents a contiguous region of memory, and Arena controls its lifetime.

Together they replace the unsafe manual buffer management of the past.

What Is a MemorySegment

A MemorySegment is a typed window over a block of memory. It knows its size and its lifetime, and every access is bounds-checked.

Segments can be off-heap (native) or wrap an on-heap array.

What Is an Arena

An Arena allocates segments and defines when they are freed. When the arena closes, all its segments become invalid in one deterministic step.

  • Arena.ofConfined(): single-thread, explicit close
  • Arena.ofShared(): multi-thread access
  • Arena.global(): never freed
  • Arena.ofAuto(): freed by the GC

Allocating a Segment

A confined arena in try-with-resources is the typical pattern. Allocate bytes, use them, and the close frees everything.

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");
    }
}

Writing and Reading

You read and write through typed accessors that take a ValueLayout and an offset. This keeps access type-safe and aligned.

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);
        }
    }
}

Allocating Typed Slots

Instead of raw byte counts, allocate by layout. arena.allocate(JAVA_INT) reserves exactly enough, properly aligned bytes for one int.

This avoids manual size arithmetic.

Arrays of Values

To store several elements, allocate a sequence layout or pass a count. Index access uses an offset computed from the element size.

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));
        }
    }
}

Bounds Checking

Reading or writing outside a segment throws IndexOutOfBoundsException. Accessing a segment after its arena closed throws IllegalStateException.

These checks are what make FFM memory-safe where JNI was not.

Confinement

A confined arena binds its segments to the thread that created them. Another thread accessing them throws WrongThreadException.

For genuinely shared memory, use Arena.ofShared(), which permits multi-thread access at a small cost.

Working with Strings

FFM offers helpers to bridge Java strings and C strings. allocateUtf8String (newer: allocateFrom) writes a null-terminated string, and getUtf8String reads one back.

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));
        }
    }
}

Choosing an Arena

Guidelines:

  • Short-lived, single-thread buffers: ofConfined()
  • Shared across threads: ofShared()
  • Lifetime managed by GC: ofAuto()
  • Process-wide constants: global()

Quick Check

Recall what determines when native memory is freed.

Recap

You learned off-heap memory management:

  • MemorySegment: a bounds-checked region of memory
  • Arena: controls lifetime (confined, shared, auto, global)
  • Typed access via ValueLayout with get/set and getAtIndex
  • Safety from bounds checks and confinement

Next: calling native functions with downcall handles.

Frequently asked questions

Is the “MemorySegment and Arena” lesson free?

Yes — the full text of “MemorySegment and Arena” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.

What will I learn in “MemorySegment and Arena”?

Allocate off-heap memory. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Java Academy?

No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “MemorySegment and Arena” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Java Academy lesson?

Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Why FFM over JNI
  2. MemorySegment and Arena
  3. Downcall Handles
  4. Layouts and Structs
← Back to Java Academy