据说从jdk22起java代码可以直接用FFM调用c函数,用一个demo测试下试试。
private static void testFFM() { //获取平台原生链接器(Windows 上可调用 msvcrt/ucrt,Linux/macOS 上调用 libc) Linker linker = Linker.nativeLinker(); //获取默认符号查找器,用于在标准 C 库中查找函数地址 SymbolLookup stdlib = linker.defaultLookup(); //查找 C 标准库函数 strlen(const char* s) -> size_t ,即在 C 标准库中查找 strlen 函数的内存地址 //find() 返回 Optional,如果找不到则抛出异常 MemorySegment strlenAddr = stdlib.find("strlen") .orElseThrow(() -> new RuntimeException("找不到 strlen 符号")); //描述 C 函数签名:返回值 long,参数为指针 FunctionDescriptor desc = FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS); // 生成一个方法句柄(MethodHandle),downcallHandle 的作用是将底层的 C 函数地址与 Java 的函数签名绑定,生成一个可以被 Java 代码像普通方法一样直接调用的句柄(Downcall) MethodHandle strlen = linker.downcallHandle(strlenAddr, desc); // 在 Arena 中分配 native 内存,写入 C 字符串并调用. // 使用 Arena(内存区域)来管理 Native 内存的生命周期 // ofConfined() 表示该内存区域是受限的,只能在当前线程中使用,且退出 try 块时自动释放 try (Arena arena = Arena.ofConfined()) { // 在 Native 内存中分配一个 C 字符串,并自动将 Java 字符串转换为 C 的格式(以 \0 结尾) MemorySegment cString = arena.allocateFrom("love u"); long length = (long) strlen.invoke(cString); System.out.println("strlen(\"love u\") = " + length); } catch (Throwable e) { throw new RuntimeException(e); } }运行:
ok.