- 適用於 JDK 23 的 GraalVM (最新)
- 適用於 JDK 24 的 GraalVM (搶先體驗)
- 適用於 JDK 21 的 GraalVM
- 適用於 JDK 17 的 GraalVM
- 封存
- 開發版本
GraalWasm
GraalWasm 是一個開源的 WebAssembly 執行環境。它以二進制格式執行 WebAssembly 程式,可用於在 Java 應用程式中嵌入和利用 WebAssembly 模組。GraalWasm 正在積極開發中,並追蹤多項 WebAssembly 擴充功能。
WebAssembly 模組系統 #
使用 GraalWasm,您可以在應用程式中載入 WebAssembly 模組、從 Java 存取它們,並使其與其他 Graal 語言相互操作。為了熟練地使用 GraalWasm,首先了解 GraalWasm 如何將 WebAssembly 的模組系統對應到 Polyglot API 非常重要。
GraalWasm 使用 WebAssembly 模組的二進制格式作為其語言。您可以使用 GraalWasm 評估的有效 Source 始終是 二進制格式中的單個 WebAssembly 模組。
以下是一種建構 WebAssembly Source
的方式
Source source = Source.newBuilder("wasm", new File("example.wasm")).name("example").build();
當您評估 WebAssembly Source
時,模組會被解析、驗證,並傳回一個模組實例作為結果值。模組實例也可以稍後從頂層繫結中檢索。頂層範圍中繫結的名稱與被評估的 Source
名稱相同。
// Evaluate the Source named "example".
Value exampleModule = context.eval(source);
// It is now accessible under the binding name "example".
assert context.getBindings("wasm").getMember("example") == exampleModule;
Source 名稱在 GraalWasm 中很重要,因為它們也用於解析模組匯入。如果模組嘗試從模組 foo
匯入符號,則 GraalWasm 會在 Source
名稱為 foo
的模組中尋找該符號。這些匯入會在 WebAssembly 模組實例的成員在給定上下文中首次被存取或執行時才會被解析。
模組實例物件 #
透過 Polyglot API 評估 WebAssembly 模組,您可以存取模組實例物件。模組實例物件會公開從 WebAssembly 模組匯出的每個符號的成員。您可以使用 getMemberKeys 取得所有已匯出符號的清單,使用 getMember 存取個別匯出,並且在可變全域變數的情況下,使用 putMember 來設定其值。
以下是各種類型的 WebAssembly 匯出如何對應到多語言值的說明
-
函式
函式會以可執行值匯出,您可以使用 execute 呼叫。函式引數和傳回值會使用類型對應在 WebAssembly 值類型和多語言值之間對應。如果函式傳回多個值,這些值會包裝在互操作陣列中。
-
全域變數
當您使用
getMember
存取已匯出的全域變數時,您會取得全域變數的值,該值會使用類型對應進行對應。如果全域變數是可變的,您也可以使用putMember
更新其值。目前,設定全域變數僅適用於數值類型,其值會根據類型對應進行對應。 -
記憶體
匯出的記憶體同時實作陣列介面和緩衝區介面。陣列介面可讓您使用 getArrayElement 和 setArrayElement 將記憶體視為位元組陣列。緩衝區介面可讓您使用 readBuffer 進行記憶體的大量複製,並使用
readBuffer*
和writeBuffer*
方法從記憶體讀取和寫入 Java 基本類型。 -
表格
匯出的表格是不透明的,無法查詢或修改。
類型對應 #
每當 WebAssembly 值透過函式呼叫、傳回值或匯出的全域變數存取傳遞到 Java 程式碼或另一個 Graal 語言時,它都會對應到多語言值。下表顯示此對應如何運作。WebAssembly 是一種靜態類型語言,所有值(區域變數、函式引數、傳回值)都有靜態類型。根據此類型,GraalWasm 會將多語言值解讀為此類型的值,如果類型不符,則會報告類型錯誤。
作為多語言值的 WebAssembly 值 #
此表描述每個 WebAssembly 值類型,以及產生的值實作哪些多語言介面。
WebAssembly 類型 | 多語言介面 |
---|---|
i32 |
符合 int 的數字 |
i64 |
符合 long 的數字 |
f32 |
符合 float 的數字 |
f64 |
符合 double 的數字 |
v128 |
16 位元組的唯讀緩衝區 |
funcref |
可執行物件 |
externref |
逐字傳回 |
將引數傳遞給 WebAssembly 函式 #
在呼叫匯出的 WebAssembly 函式時,必須遵守其確切的類型簽名。下表提供每個可能的 WebAssembly 參數類型的預期引數類型。
WebAssembly 參數類型 | 預期引數類型 |
---|---|
i32 |
int |
i64 |
long |
f32 |
float |
f64 |
double |
v128 |
從 WebAssembly 接收的現有 v128 值 |
funcref |
WebAssembly 的 ref.null 或已匯出的 WebAssembly 函式 |
externref |
可以是任何值(只有 WebAssembly 的 ref.null 會被 ref.is_null 視為 null) |
選項 #
GraalWasm 可以使用多個選項進行設定。當使用 Polyglot API 時,選項會以程式設計方式傳遞至 Context 物件
Context.newBuilder("wasm").option("wasm.Builtins", "wasi_snapshot_preview1").build();
請參閱 多語言程式設計 參考資料,以取得有關如何以程式設計方式設定選項的更多資訊。
可用的選項分為穩定選項和實驗性選項。實驗性選項不保證未來支援,並且可能會隨版本而變更。如果實驗性選項與 wasm
啟動器一起使用,則必須提供 --experimental-options
選項。當使用 Context
時,必須在 Context.Builder 上呼叫方法 allowExperimentalOptions(true)。
穩定選項 #
提供以下穩定選項
-
--wasm.Builtins
:公開一些 GraalWasm 提供的內建模組。值的語法為[<linkingName>:]<builtinModuleName>,[<linkingName>:]<builtinModuleName>,...
。要求的模組以逗號分隔。每個模組都可選擇性地以冒號分隔的連結名稱作為前綴。如果指定了連結名稱,則會以給定的連結名稱匯出模組。否則,模組會以其內建模組名稱匯出。提供的內建模組為
spectest
:一個簡單函式模組,適用於編寫測試案例。此模組實作與 WebAssembly 參考解譯器的 spectest 模組相同的介面。使用它可以執行 核心 WebAssembly 規格測試。wasi_snapshot_preview1
:GraalWasm 實作的 WebAssembly 系統介面快照預覽 1。涵蓋大多數已記錄的 API,但套接字和信號支援除外。
-
--wasm.WasiMapDirs
:一個預先開啟的目錄清單,應該可以透過 WebAssembly 系統介面 API 存取。值的語法為[<virtualDir>::]<hostDir>,[<virtualDir>::]<hostDir>,...
。預先開啟的目錄以逗號分隔。每個目錄都可選擇性地以雙冒號分隔的虛擬路徑作為前綴。在 WebAssembly 模組中,該目錄可在虛擬路徑上使用。如果省略虛擬路徑,則預先開啟的目錄將與主機檔案系統上的路徑相同。必須設定此選項,以允許使用 WASI 的模組存取檔案系統。僅會授予對這些預先開啟的目錄內容的存取權。
實驗性選項 #
請注意,這些選項是實驗性的,不保證未來會維護或支援。若要使用它們,必須提供 --experimental-options
選項,或必須在 Context
上啟用實驗性選項,請參閱上方。
以下選項對應於為 WebAssembly 標準新增新功能的特性提案。接受的值為 true
以啟用特性,以及 false
以停用特性。已合併至 WebAssembly 規格中的特性在 GraalWasm 中預設為啟用。尚未合併至規格中的特性預設為停用。使用者可以覆寫預設值,以試驗即將推出的特性或選擇不使用標準化特性。
-
--wasm.BulkMemoryAndRefTypes
:啟用對批量記憶體操作特性和參考類型特性的支援,公開用於高效記憶體初始化的指令,並新增對一級不透明參考的支援。預設值為true
。 -
--wasm.ExtendedConstExpressions
:啟用對擴展常數表達式特性的支援,在常數表達式中新增對算術指令的有限支援。預設值為false
。 -
--wasm.Memory64
:啟用對Memory64 特性的支援,讓記憶體可以大於 4 GiB。預設值為false
。 -
--wasm.MultiMemory
:啟用對多個記憶體特性的支援,允許模組具有多個記憶體。預設值為false
。 -
--wasm.MultiValue
:啟用對多值特性的支援,讓函式可以傳回多個值。預設值為true
。 -
--wasm.SaturatingFloatToInt
:啟用對非陷阱浮點數到整數轉換特性的支援,新增會飽和而非以陷阱失敗的浮點數到整數轉換指令。預設值為true
。 -
--wasm.SignExtensionOps
:啟用對符號擴展運算子特性的支援,新增用於擴展帶符號整數值的指令。預設值為true
。 -
--wasm.SIMD
:啟用對固定寬度 SIMD 特性的支援,引入新的值類型v128
以及用於 SIMD 算術的相關指令。預設值為true
。 -
--wasm.Threads
:啟用對執行緒特性的支援,讓 WebAssembly 模組可以使用新的指令來進行原子記憶體存取。預設值為false
。
使用 GraalWasm 啟動器 #
GraalWasm 獨立程式提供 wasm
啟動器,您可以使用它來執行編譯為 WebAssembly 二進位模組的程式。
wasm [OPTION...] [--entry-point=FN] FILE [ARG...]
-
[選項...]
選項包含 GraalWasm 引擎選項,以
--wasm.
作為前綴,例如--wasm.WasiMapDirs=preopened-dir
,以及任何其他多語言引擎選項。當使用wasm
啟動器時,預設會設定--wasm.Builtins=wasi_snapshot_preview1
選項,以便您可以直接執行針對 WebAssembly 系統介面快照預覽 1 編譯的模組。可用的選項記錄在選項中。您也可以將
--help:wasm
選項傳遞給wasm
啟動器,以取得 GraalWasm 引擎選項的完整清單。若要包含內部選項,請使用--help:wasm:internal
。請注意,這些清單都包含穩定、受支援的選項和實驗性選項。 -
[--entry-point=FN]
您可以指定
--entry-point
選項來選擇要用作模組進入點的匯出函式,例如--entry-point=my_custom_main_fn
。如果缺少--entry-point
選項,GraalWasm 將嘗試自動偵測進入點。它會先尋找名為_start
的匯出函式,然後尋找名為_main
的匯出函式。找到的第一個此類函式將由wasm
啟動器執行為進入點。 -
檔案
這是將要執行的二進位模組的路徑。
-
[ARG...]
程式引數,可透過 WASI args_get 和 args_sizes_get 函式存取。