- 適用於 JDK 23 的 GraalVM (最新)
- 適用於 JDK 24 的 GraalVM (搶先體驗)
- 適用於 JDK 21 的 GraalVM
- 適用於 JDK 17 的 GraalVM
- 封存
- 開發建置
GraalVM 與原生程式碼的互動
GraalVM LLVM 執行階段允許使用者執行以傳統方式直接編譯為原生程式碼的語言所撰寫的程式碼。這些語言通常不需要任何受管理的執行階段或 VM 即可執行。因此,需要特別注意此程式碼與 GraalVM 的受管理執行階段之間的互動,尤其是當程式碼使用某些底層功能時。
對底層系統呼叫的有限存取 #
- 訊號處理是根據以下假設執行的
- 受管理的執行階段假設它具有完全控制權來處理所有訊號。
- 已安裝的訊號處理常式行為可能與原生執行時不同。
- 處理程序控制和執行緒是根據以下方面完成的
- GraalVM 假設它對執行緒具有完全控制權。
- 透過
pthreads
函式庫支援多執行緒 (例如,pthread_create
)。 - 不支援直接使用與處理程序相關的系統呼叫,例如
clone
、fork
、vfork
等。 - 不支援
exec
函式系列。
記憶體配置 #
在 GraalVM 上執行的處理程序的記憶體和堆疊配置與直接原生執行時不同。尤其是,不可能對全域變數、堆疊變數等的相對位置做出假設。
只能使用 GraalVM API 來走訪堆疊。程式碼和資料之間有嚴格的分隔。自我修改程式碼將無法運作。不支援對程式碼指標進行讀取、寫入和指標運算。
與原生模式中的系統函式庫互動 #
在原生執行模式 (預設模式) 中,在 GraalVM LLVM 執行階段上執行的程式碼可以呼叫真實的原生函式庫 (例如,系統函式庫)。這些呼叫的行為類似於 Java 中的 JNI 呼叫:它們會暫時離開受管理的執行環境。
由於這些函式庫中執行的程式碼不受 GraalVM 的控制,因此該程式碼基本上可以執行任何操作。尤其是,不適用多重內容隔離,並且會繞過虛擬檔案系統等 GraalVM API。
請注意,這尤其適用於大多數標準 C 函式庫。
受管理執行模式 #
受管理模式 (使用 --llvm.managed
選項啟用) 是一種特殊的執行模式,其中 LLVM 執行階段純粹在受管理模式下執行,類似於所有其他 GraalVM 支援的語言。
注意:受管理模式僅適用於 Oracle GraalVM。
在此模式下,根據設計,不允許呼叫原生程式碼和存取原生記憶體。所有記憶體都由垃圾收集器管理,並且所有應執行的程式碼都需要編譯為位元碼。
指標運算只能在 C 標準允許的範圍內進行。尤其是,會防止溢位,並且無法透過超出範圍的存取來存取不同的配置。所有此類無效的存取都會導致執行階段例外狀況,而不是未定義的行為。
在受管理模式下,GraalVM 會模擬一個虛擬 Linux/AMD64 作業系統,其中 musl libc 和 libc++ 作為 C/C++ 標準函式庫。所有程式碼都需要針對該系統進行編譯,然後才能用於在 GraalVM 支援的任何架構或作業系統上執行。系統呼叫會被虛擬化並透過適當的 GraalVM API 進行路由。
原生程式碼和受管理語言之間的 Polyglot 互動 #
當在 LLVM 語言 (例如,C/C++) 和受管理語言 (例如 JavaScript、Python 或 Ruby) 之間使用多語言互通性時,必須小心處理手動記憶體管理。請注意,本節僅適用於原生執行模式 (預設)。在受管理模式下 (使用 --llvm.managed
選項啟用,且僅適用於 Oracle GraalVM),LLVM 執行階段本身的行為類似於受管理語言,並且多語言互動與其他受管理語言之間相同。
- 要考慮的垃圾收集政策
- 受管理語言物件的指標由垃圾收集器管理,因此不需要手動釋放它們。
- 另一方面,來自 LLVM 程式碼的配置指標 (例如,
malloc
) 不受垃圾收集器的控制,因此需要手動解除配置它們。
- 要考慮的非受管理堆積政策
- 原生記憶體 (例如,
malloc
、資料區段、執行緒本機) 不受垃圾收集器的控制。 - 受垃圾收集器控制的外部物件的指標無法直接儲存在原生記憶體中。
- 有可用的控制代碼函式可解決此限制 (請參閱
graalvm/llvm/handles.h
)。
- 原生記憶體 (例如,