本机镜像中的外部函数和内存 API

外部函数和内存 (FFM) API 是一个接口,它使 Java 代码能够与原生代码交互,反之亦然。它在 JDK 22 中通过 JEP 454 进行了最终确定。本机镜像中的支持目前处于实验阶段,必须使用 -H:+ForeignAPISupport(除了 -H:+UnlockExperimentalVMOptions)明确启用。允许执行“受限”原生操作(包括创建对原生代码调用或从原生代码调用的句柄)的模块必须使用 --enable-native-access= 选项指定。本页概述了本机镜像中对 FFM API 的支持。

外部内存 #

通常支持外部内存功能。目前不支持共享区域。

外部函数 #

FFM API 使 Java 代码能够向下调用原生函数,反过来也允许原生代码向上调用以通过方法句柄调用 Java 代码。这两种调用分别称为“向下调用”和“向上调用”,统称为“外部调用”。

注意:目前,仅支持 x64 架构上的外部调用。具体来说,x64 Linux、Windows 和 MacOS 上支持向下调用,而仅支持 x64 Linux 上的向上调用。

查找原生函数 #

FFM API 提供 SymbolLookup 接口来按名称在原生库中查找函数。SymbolLookup.loaderLookup() 当前是唯一支持的 SymbolLookup 类型。

注册外部调用 #

为了在运行时执行对原生代码的调用,必须在镜像构建时生成支持代码。因此,必须向 native-image 工具提供描述符,以描述可以在运行时对哪些函数执行向下调用。

可以使用自定义 Feature 来注册这些描述符,例如

import static java.lang.foreign.ValueLayout.*;

class ForeignRegistrationFeature implements Feature { 
  public void duringSetup(DuringSetupAccess access) {
    RuntimeForeignAccess.registerForDowncall(FunctionDescriptor.ofVoid());
    RuntimeForeignAccess.registerForUpcall(FunctionDescriptor.ofVoid());
    RuntimeForeignAccess.registerForDowncall(FunctionDescriptor.ofVoid(), Linker.Option.critical(false));
    RuntimeForeignAccess.registerForUpcall(FunctionDescriptor.of(JAVA_INT, JAVA_INT));
    RuntimeForeignAccess.registerForUpcall(FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_INT));
    RuntimeForeignAccess.registerForDowncall(FunctionDescriptor.of(ADDRESS, JAVA_INT, JAVA_INT), Linker.Option.firstVariadicArg(1));
    RuntimeForeignAccess.registerForDowncall(FunctionDescriptor.ofVoid(JAVA_INT), Linker.Option.captureCallState("errno"));
  }
}

要激活自定义功能,请将 --features=com.example.ForeignRegistrationFeature 选项(功能类的完全限定名称)传递给 native-image。建议 使用native-image.properties 文件 来执行此操作。

联系我们