JDK Enhancement Proposal (JEP) 191 defines the Java Foreign Function Interface (FFI), which are interfaces that can bind native functions to Java methods and can manage blocks of native memory. This JEP will make it easier to add new native-level features to the JDK and help provide a standard FFI for use in Java development. Java Native Interface (JNI) is the current standard programming interface for writing Java native code. JNI is not a simple way to create native functions, and this gave birth to libraries like Java Native Access (JNA) and Java Native Runtime (JNR). Both JNA and JNR are built on top of JNI, and JEP 191 will likely be based on JNR.
JEP 191 provides a Foreign Function Interface at the Java level, similar to JNA or JNR. It will allow easy access to native functions, and will manage native memory at the JVM level. It will also support a future JSR for a standard Java FFI. The Java FFI API can be used for implementing native-backed features like NIO, advanced file system metadata, and process management. Using the FFI API will be the preferred way to bind native code and memory, instead of JNI. JEP 191 does not include enhancements to JNI, although these may go into the JSR process.
JNI is the current standard programming interface for writing Java native methods and embedding the Java virtual machine into native applications. It governs the boundary between the JVM and the unmanaged native environment, providing protocols for data marshalling and object lifecycle management. According to JEP 191, these aspects of JNI are most painful to developers:
- Requiring developers to write C code means they have to have expertise of a world completely different from Java.
- Using JNI requires expertise usually not found in typical C and Java developers, since the developer must have at least some understanding of how the JVM manages memory and code.
- Developers must be able to build that code for each platform they wish to support, or provide appropriate tooling for end-users to do the same.
- The performance of JNI-based libraries is usually poor compared to the same library bound into a native application.
- JNI acts as an opaque boundary for security. The JDK does not know what calls the functions in that library might use or whether the code in that library could compromise the stability or security of the JVM.
The difficulties of JNI can be addressed by a built-in FFI API for the JDK. The Java FFI would be easier to implement, and it would not require as much expertise in JVM internals and various host platforms. The FFI API will provide the following:
- A metadata system to describe native library calls and native memory structure.
- Mechanisms for discovering and loading native libraries.
- Mechanisms for binding, based on metadata, a library/function or a memory structure to a Java endpoint.
- Code for marshalling and unmarshalling Java data types to native data types.
The need for a Java FFI has spawned the JNA and JNR libraries. The JNA library is more widely used. The JNR library is more comprehensive since it implements various levels of abstraction, provides function and memory metadata, abstracts away library and function binding. JNR has been in heavy use by the JRuby project and will likely form the basis of JEP 191.