A Quick Intro To Java 21 Foreign Function and Memory (FFM) API

Photo of Luqman Saeed by Luqman Saeed

Java 21 introduces the Foreign Function and Memory (FFM) API, which allows Java programs to interoperate with code and data outside the Java runtime. Java operates within a managed environment known as the Java Virtual Machine (JVM). The JVM serves as an abstraction layer between the executing Java code and the underlying hardware and OS. One of the core design principles behind the JVM is to provide a secure and isolated environment for Java applications to run. This isolation is beneficial for several reasons, including security and stability; it mitigates risks such as unauthorized access to system resources or memory corruption, which could lead to vulnerabilities like buffer overflows.

However, this isolation can sometimes be a limitation when Java applications need to interact with system-level resources or libraries written in other programming languages. For instance, you might have a performance-critical application that requires the speed of a native library written in C or C++. Or perhaps you're working on an application that needs to interface with hardware devices directly, something that's usually done via native libraries. In such cases, Java's traditional approach has been to use the Java Native Interface (JNI). While powerful, JNI comes with its own set of complexities and risks, such as memory leaks and crashes, which can undermine the robustness of the Java application.

This is whereJava 21's Foreign Function and Memory (FFM) API comes into play. The FFM API allows Java programs to interoperate safely and more easily with code and data outside the Java runtime. Unlike JNI, which often involves brittle and error-prone boilerplate code, the FFM API aims to provide a more straightforward and safer method for calling native libraries and manipulating native data. This opens up new possibilities for Java applications, enabling them to leverage the performance or capabilities of native libraries without sacrificing the security and stability that come with the JVM's isolated environment.

The following code shows calling the strlen function in C to determine the length of a Java String passed to it. Of course this is just an example to show how you can use the API to carry out such cross method calls.

public static void main(String[] args) throws Throwable {

// This line creates a SymbolLookup object, which can be used to find native symbols on the C library path.

SymbolLookup stdlib = Linker.nativeLinker().defaultLookup();


// This line creates a MethodHandle object for the strlen() function. The MethodHandle object contains all

// the information needed to call the native function, such as the function pointer and the function signature.

MethodHandle strlen = Linker.nativeLinker().downcallHandle(

stdlib.find("strlen").orElseThrow(),

FunctionDescriptor.of(JAVA_LONG, ADDRESS));

// This line creates an Arena object. An Arena is a region of memory that can be used to allocate off-heap

// memory. The try-with-resources statement ensures that the Arena object is automatically closed when the code

// block exits.

try (Arena offHeap = Arena.ofConfined()) {

// This line allocates a region of off-heap memory to store the string "Java 21 rocks! Yay!!!". The

// MemorySegment object represents the allocated off-heap memory.

MemorySegment str = offHeap.allocateUtf8String("Java 21 is the issh");


// This line calls the strlen() function to calculate the length of the string "Java 21 works". The strlen()

// function takes a pointer to a string as input and returns the length of the string as output.

long len = (long) strlen.invoke(str);
System.out.println("len = " + len);

}

}
This example shows how to load a native library, get a function pointer, allocate memory for the function arguments, set the function arguments, call the native function, and get the result.

The FFM API also provides a number of other features, such as:

  • Support for calling foreign functions with complex argument types, such as strings and arrays
  • Support for returning complex values from foreign functions
  • Support for accessing and modifying foreign memory
  • Support for memory management

As you can see, the FFM API is a powerful tool that can be used to write Java programs that interact with code and data outside the Java runtime. It is a safe, efficient, and easy-to-use alternative to JNI. Some situations where you might want to use this API are:

  • When you need to call a native function. The FFM API provides a safe and efficient way to call native functions from Java. This can be useful if you need to access functionality that is only available in a native library.
  • When you need to access native data. The FFM API allows you to access and modify native data from Java. This can be useful if you need to read or write data to a file, or if you need to interact with a native device.
  • When you need to improve the performance of your Java program. The FFM API can be used to improve the performance of your Java program by allowing you to call native functions that are optimized for speed.
  • When you need to write a Java program that is portable across different platforms. The FFM API can be used to write Java programs that are portable across different platforms by allowing you to call native functions that are available on all platforms.

Examples  of specific situations where you might want to use the FFM API:

  • To access a machine learning library that is written in C or C++.
  • To interact with a hardware device that is controlled by a native driver.
  • To implement a high-performance algorithm that is written in C or C++.
  • To write a Java program that needs to be portable to different platforms, such as Windows, Linux, and macOS.

If you are writing a Java program that needs to interact with native code, the FFM API is a good option to consider. It is a safe, efficient, and portable way to call native functions and access native data.

Enjoyed this article? See more of our Java 21 content:

And remember, we have launched our own fully-managed cloud native application runtime, Payara Cloud. 

Fully managed Jakarta EE Deployment. ✅Handles Kubernetes for you.✅ 15 day free trial available.✅

Payara Cloud.

TRY FREE.

 

 

Comments