Native Image 中的外部函式與記憶體 API

外部函式與記憶體 (FFM) API 是一個介面,可讓 Java 程式碼與原生程式碼互動,反之亦然。它在 JDK 22 中透過 JEP 454 完成。目前在 Native Image 中的支援是實驗性的,必須使用 -H:+ForeignAPISupport (除了 -H:+UnlockExperimentalVMOptions) 明確啟用。允許執行「受限制」原生操作的模組 (包括建立呼叫原生程式碼或從原生程式碼呼叫的控制代碼) 必須使用 --enable-native-access= 選項指定。此頁面概述了 Native Image 中 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檔案 來執行此操作。

與我們聯繫