外部函数与内存API:安全调用C库
使用FFM API(JEP 454)替代JNI,在Java中直接调用C标准库函数并管理堆外内存,避免native方法复杂性。 · 难度:入门 · +10XP
不用JNI:用MemorySegment调用C的malloc和free
FFM API提供类型安全的内存段和符号查找。本教程演示如何通过MethodHandle调用系统库的strlen函数,并使用SegmentAllocator分配堆外内存。重点讲解MemoryLayout描述结构体布局、arena控制生命周期、以及防止use-after-free的引用机制。对比JDK 19以来的API演变,展示调用printf的完整过程。
// 获取C库的strlen函数
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle strlen = linker.downcallHandle(
stdlib.find("strlen").get(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
);
// 分配C字符串并调用
try (Arena arena = Arena.ofConfined()) {
MemorySegment str = arena.allocateUtf8String("Hello FFM");
long len = (long) strlen.invoke(str);
System.out.println("Length: " + len);
}