โ— Shell
clean mode source โ†—

Calling out to C code from Java

Home / Language / Calling out to C code from Java

Code Comparison

public class CallCFromJava {
    static { System.loadLibrary("strlen-jni"); }
    public static native long strlen(String s);
    public static void main(String[] args) {
        long ret = strlen("Bambi");
        System.out.println("Return value " + ret); // 5
    }
}

// Run javac -h to generate the .h file, then write C:
// #include "CallCFromJava.h"
// #include <string.h>
// JNIEXPORT jlong JNICALL Java_CallCFromJava_strlen(
//     JNIEnv *env, jclass clazz, jstring str) {
//     const char* s = (*env)->GetStringUTFChars(env, str, NULL);
//     jlong len = (jlong) strlen(s);
//     (*env)->ReleaseStringUTFChars(env, str, s);
//     return len;
// }
void main() throws Throwable {
    try (var arena = Arena.ofConfined()) {
        // Use any system library directly โ€” no C wrapper needed
        var stdlib = Linker.nativeLinker().defaultLookup();
        var foreignFuncAddr = stdlib.find("strlen").orElseThrow();
        var strlenSig = FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS);
        var strlenMethod = Linker.nativeLinker() .downcallHandle(foreignFuncAddr, strlenSig);
        var ret = (long) strlenMethod.invokeExact(arena.allocateFrom("Bambi"));
        System.out.println("Return value " + ret); // 5
    }
}

// Your own C library needs no special Java annotations:
// long greet(char* name) {
//     printf("Hello %s\n", name);
//     return 0;
// }

Why the modern way wins

๐Ÿ‘

C code stays plain C

The C function requires no JNI annotations or JNIEnv boilerplate โ€” any existing C library can be called as-is.

โšก

More flexible

Directly call most existing C/C++ libraries without writing adapter code or generating header files.

๐Ÿ› ๏ธ

Easier workflow

No need to stop, run javac -h, and implement the interface defined in the generated .h file.

Old Approach

JNI (Java Native Interface)

Modern Approach

FFM (Foreign Function & Memory API)

JDK Support

Calling out to C code from Java

Available

Standardized in JDK 22 (March 2024); previously incubating since JDK 14

How it works

Java has two approaches for calling native C/C++ code: the traditional JNI and the modern FFM API. With JNI, you declare a method as native, run javac -h to generate a C header file, then implement the function using the cumbersome JNI C API (JNIEnv, jstring, etc.). FFM, introduced as a standard API in Java 22, eliminates all of that: C code is just plain C โ€” no JNI conventions needed. This makes it far easier to call existing C/C++ libraries without modification. The Java side uses Arena for safe off-heap memory management and MethodHandle for the downcall, ensuring both flexibility and safety.

Related Documentation

Proof