Llamar a código C desde Java
FFM permite a Java llamar directamente a bibliotecas C sin el código repetitivo de JNI ni conocimiento de Java en el lado C.
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;
// }
El código C permanece como C puro
La función C no requiere anotaciones JNI ni código JNIEnv repetitivo — cualquier biblioteca C existente puede llamarse tal cual.
Más flexible
Llama directamente a la mayoría de las bibliotecas C/C++ existentes sin escribir código adaptador ni generar archivos de encabezado.
Flujo de trabajo más sencillo
No es necesario detenerse, ejecutar javac -h e implementar la interfaz definida en el archivo .h generado.
Estandarizado en JDK 22 (marzo 2024); anteriormente en incubación desde JDK 14
Java tiene dos enfoques para llamar a código nativo C/C++: el tradicional JNI y la moderna API FFM. Con JNI, se declara un método como native, se ejecuta javac -h para generar un archivo de encabezado C y se implementa la función usando la complicada API JNI de C (JNIEnv, jstring, etc.). FFM, introducida como API estándar en Java 22, elimina todo eso: el código C es simplemente C puro — sin necesidad de convenciones JNI. Esto facilita mucho la llamada a bibliotecas C/C++ existentes sin modificaciones. El lado Java usa Arena para la gestión segura de memoria fuera del heap y MethodHandle para el downcall, garantizando flexibilidad y seguridad.