【Java】JDK 17 Foreign Function & Memory API 替代 JNI

2023-12-14 21:42:03

当使用Java与本地代码(如C和C++)交互时,一直以来都需要使用JNI(Java Native Interface)来进行繁琐的手动映射。然而,JDK 17引入了Foreign Function & Memory API,为 Java 开发者提供了一种更简单和安全的方式来调用本地函数并操作内存。

Foreign Function & Memory API 的目标是简化 Java 与本地代码的交互过程,并提供更安全的方式来处理本地代码。它允许 Java 程序直接调用本地函数,无需手动编写JNI代码。这使得在 Java 中调用本地函数和操作内存变得更加直观和易于理解。

printf 示例

  首先,需要导入相关的类和接口:
import jdk.incubator.foreign.CLinker;
import jdk.incubator.foreign.FunctionDescriptor;
import jdk.incubator.foreign.LibraryLookup;
import jdk.incubator.foreign.MemoryAddress;
import static jdk.incubator.foreign.MemoryAddress.NULL;

然后,加载本地库并查找要调用的函数:

LibraryLookup libc = LibraryLookup.ofDefault();
MemoryAddress printfFn = libc.lookup("printf").orElseThrow();

接下来,定义本地函数的接口和参数:

FunctionDescriptor printfDescriptor = FunctionDescriptor.of(CLinker.C_POINTER, CLinker.C_CHAR, CLinker.C_POINTER);

然后,分配内存并将数据复制到本地内存中:

MemoryAddress formatStr = MemoryAddress.ofUtf8String("Hello, %s!\n");
MemoryAddress nameStr = MemoryAddress.ofUtf8String("World");

接下来,调用本地函数并传递参数:

CLinker.C_POINTER.execute(printfFn, printfDescriptor, formatStr, nameStr);

最后,释放先前分配的内存:

MemoryAddress.free(formatStr);
MemoryAddress.free(nameStr);

这个示例演示了如何使用Foreign Function & Memory API调用本地函数并输出格式化的字符串。

加减乘除示例

首先,导入相关的类和接口:

import jdk.incubator.foreign.CLinker;
import jdk.incubator.foreign.FunctionDescriptor;
import jdk.incubator.foreign.LibraryLookup;
import jdk.incubator.foreign.MemoryAddress;
import static jdk.incubator.foreign.MemoryAddress.NULL;

然后,加载自定义函数库并查找要调用的函数:

LibraryLookup myLibrary = LibraryLookup.ofPath("/path/to/your/library.so");
MemoryAddress addFn = myLibrary.lookup("add").orElseThrow();
MemoryAddress subtractFn = myLibrary.lookup("subtract").orElseThrow();
MemoryAddress multiplyFn = myLibrary.lookup("multiply").orElseThrow();
MemoryAddress divideFn = myLibrary.lookup("divide").orElseThrow();

接下来,定义本地函数的接口和参数:

// 这里假设四个函数的返回类型和参数类型都是整数(CLinker.C_INT)。根据实际情况,可能需要调整这些类型
FunctionDescriptor addDescriptor = FunctionDescriptor.of(CLinker.C_INT, CLinker.C_INT, CLinker.C_INT);
FunctionDescriptor subtractDescriptor = FunctionDescriptor.of(CLinker.C_INT, CLinker.C_INT, CLinker.C_INT);
FunctionDescriptor multiplyDescriptor = FunctionDescriptor.of(CLinker.C_INT, CLinker.C_INT, CLinker.C_INT);
FunctionDescriptor divideDescriptor = FunctionDescriptor.of(CLinker.C_INT, CLinker.C_INT, CLinker.C_INT);

然后,调用本地函数并传递参数:

int result1 = CLinker.C_INT.execute(addFn, addDescriptor, 5, 3);
int result2 = CLinker.C_INT.execute(subtractFn, subtractDescriptor, 8, 2);
int result3 = CLinker.C_INT.execute(multiplyFn, multiplyDescriptor, 4, 6);
int result4 = CLinker.C_INT.execute(divideFn, divideDescriptor, 15, 3);

最后,打印结果:

System.out.println("Addition result: " + result1);
System.out.println("Subtraction result: " + result2);
System.out.println("Multiplication result: " + result3);
System.out.println("Division result: " + result4);

这个示例演示了如何使用Foreign Function & Memory API调用本地函数进行加减乘除运算。

文章来源:https://blog.csdn.net/m0_47406832/article/details/134925011
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。