
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
Concept | Description |
---|---|
MemorySegment | A block of off-heap memory |
MemoryLayout | Describes the layout (structure) of memory |
Linker | Connects to native libraries (like libc ) |
SymbolLookup | Finds 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
Feature | JNI | FFM 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
- Why is the FFM API a better alternative to JNI?
- How does
Arena
help manage memory safely? - 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) 😊🚀