Language Продвинутый

FFM позволяет Java напрямую вызывать C-библиотеки без шаблонного кода JNI и без знания Java на стороне C.

✕ Java 1.1+
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;
// }
✓ Java 22+
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;
// }
Заметили проблему в этом коде? Сообщите нам.
👁

C-код остаётся чистым C

Функции C не нужны JNI-аннотации или шаблонный JNIEnv — любая существующая C-библиотека может быть вызвана напрямую.

Более гибкий подход

Большинство существующих библиотек C/C++ можно вызывать напрямую без написания адаптерного кода или генерации заголовочных файлов.

🛠️

Упрощённый рабочий процесс

Не нужно останавливаться, запускать javac -h или реализовывать интерфейс, определённый в сгенерированном .h-файле.

Старый подход
JNI (Java Native Interface)
Современный подход
FFM (Foreign Function & Memory API)
Начиная с JDK
22
Сложность
Продвинутый
Вызов C-кода из Java
Доступно

Стандартизирован в JDK 22 (март 2024); ранее находился в инкубационной фазе с JDK 14

Java предлагает два подхода для вызова нативного кода C/C++: традиционный JNI и современный FFM API. При использовании JNI нужно объявить метод как native, запустить javac -h для генерации заголовочного файла C и реализовать функцию с громоздким JNI C API (JNIEnv, jstring и т.д.). FFM, ставший стандартным API в Java 22, устраняет всё это: C-код остаётся чистым C — никаких JNI-соглашений не требуется. Это значительно упрощает вызов существующих библиотек C/C++ без каких-либо изменений. На стороне Java используется Arena для безопасного управления памятью вне кучи и MethodHandle для downcall, что обеспечивает гибкость и безопасность.