Lesson 27: Foreign Function & Memory API (FFM API) – Java 22 (Preview Feature)

The Foreign Function & Memory API (FFM API) introduced in Java 22 (as a preview) is a powerful tool that allows Java programs to:

Call native code (like C libraries)
Access off-heap memory safely
Replace the need for JNI (Java Native Interface)

This feature is part of Project Panama, which focuses on improving interoperability between Java and native code.


1. What Problem Does FFM Solve?

🔴 Before Java 22, calling C/C++ libraries required using JNI (Java Native Interface):

  • Verbose and error-prone
  • Hard to maintain
  • Unsafe memory management

🟢 Now with FFM API:

  • ✅ Safer memory access
  • ✅ Easier interop with native functions
  • ✅ No need to write native glue code in C

2. FFM Core Concepts

ConceptDescription
MemorySegmentA block of off-heap memory
MemoryLayoutDescribes the layout (structure) of memory
LinkerConnects to native libraries (like libc)
SymbolLookupFinds native function symbols

3. Example: Allocating and Using Off-Heap Memory

📌 Allocating off-heap memory (like malloc in C):

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

public class Main {
    public static void main(String[] args) {
        try (Arena arena = Arena.ofConfined()) {
            MemorySegment segment = arena.allocate(4); // 4 bytes
            segment.set(ValueLayout.JAVA_INT, 0, 42);  // Store value

            int value = segment.get(ValueLayout.JAVA_INT, 0);
            System.out.println("Stored value: " + value);
        }
    }
}

Output:

Stored value: 42

✔ The memory is off-heap and automatically released when the Arena is closed.


4. Example: Calling a Native C Function (e.g., strlen)

🔹 Let’s call the standard C function strlen() using FFM.

📌 FFM Example: Calling strlen() from libc

import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;

public class Main {
    public static void main(String[] args) throws Throwable {
        Linker linker = Linker.nativeLinker(); // Connect to native libraries
        SymbolLookup libc = SymbolLookup.systemLookup(); // Get standard C symbols

        FunctionDescriptor strlenDesc = FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS);
        MethodHandle strlen = linker.downcallHandle(libc.find("strlen").get(), MethodType.methodType(long.class, MemorySegment.class), strlenDesc);

        try (Arena arena = Arena.ofConfined()) {
            MemorySegment str = arena.allocateUtf8String("Java FFM API!");
            long len = (long) strlen.invoke(str);

            System.out.println("Length: " + len); // ✅ Should be 13
        }
    }
}

Output:

Length: 13

✔ You just called C code from Java without JNI! 🙌


5. Real-World Use Cases

🚀 Use the FFM API when:

  • You need high-performance access to C libraries (e.g., image/audio/video processing, AI models)
  • You want to manipulate memory directly (like in C/C++)
  • You’re replacing legacy JNI code

6. Benefits of FFM API over JNI

FeatureJNIFFM API (Java 22+)
Verbose?✅ Yes❌ No
Unsafe memory access✅ Risk of memory leaks❌ Safer with arenas
Manual native code✅ Required❌ Not needed
Performance⚠ Depends✅ Highly optimized
Easy to use?❌ Not really✅ Cleaner API

7. Preview Feature Note

🚨 FFM is still a preview API in Java 22.
👉 You must enable it with the --enable-preview flag to compile and run code.

javac --enable-preview --release 22 Main.java
java --enable-preview Main

Lesson Reflection

  1. Why is the FFM API a better alternative to JNI?
  2. How does Arena help manage memory safely?
  3. Can you think of a use case in your current work/project where calling native code from Java would be helpful?

The next feature (e.g. Java 22’s enhanced unnamed patterns/variables or another concept you’re curious about) 😊🚀

Java Sleep