- 適用於 JDK 23 的 GraalVM (最新)
- 適用於 JDK 24 的 GraalVM (搶先體驗)
- 適用於 JDK 21 的 GraalVM
- 適用於 JDK 17 的 GraalVM
- 封存
- 開發版本
實驗性代理程式選項
native-image-agent
工具具有一些目前為實驗性的選項,這些選項可能會在未來版本中啟用,但也可能被變更或完全移除。這些選項在此處說明。
支援預定義的類別 #
Native-image 需要在影像建置時知道所有類別 (「封閉世界假設」)。然而,Java 支援在執行階段載入新的類別。為了模擬類別載入,可以告知代理程式追蹤動態載入的類別,並儲存其位元碼,以供影像建置器稍後使用。此功能可透過將 experimental-class-define-support
新增至代理程式選項字串來啟用,例如: -agentlib:native-image-agent=config-output-dir=config,experimental-class-define-support
。除了標準的組態檔案之外,代理程式還會在組態輸出目錄中建立一個 agent-extracted-predefined-classes
目錄,並隨時寫入新載入類別的位元碼。然後,影像建置器可以使用組態目錄,而無需額外的調整。這些類別將在影像建置期間載入,但不會初始化或提供給應用程式使用。在執行階段,如果嘗試載入名稱和位元碼與追蹤期間遇到的類別之一相同的類別,則會將預定義的類別提供給應用程式。
已知限制 #
- 原生影像每個執行僅支援透過單一類別載入器「載入」一個預定義的類別一次。
- 預定義的類別會在執行階段「載入」時初始化,無法在建置時初始化。
- 代理程式會收集所有非由 Java VM 的內建類別載入器 (有一些例外) 載入的類別,也就是從類別路徑或模組路徑載入的類別。這包括由任何自訂類別載入器載入的類別。
- 名稱或位元碼中包含不同資料 (例如循序或隨機數字或時間戳記) 所產生的類別,通常無法在執行階段與預定義的類別比對。在這些情況下,需要調整這些類別的產生方式。
列印具有來源的組態 #
為了進行偵錯,了解某些組態項目的來源可能很有用。透過將 experimental-configuration-with-origins
提供給代理程式選項字串,代理程式會輸出組態檔案,其中組態項目會細分為其來源的呼叫上下文 (堆疊追蹤),並以樹狀結構顯示。此選項應與 config-output-dir=<path>
一起使用,以告知代理程式組態檔案的輸出位置。範例代理程式選項字串:-agentlib:native-image-agent=config-output-dir=config-with-origins/,experimental-configuration-with-origins
從代理程式的輸出中省略組態 #
代理程式可以省略現有組態檔案中存在的追蹤組態項目。有兩種方式可以指定這些現有組態檔案。
- 透過使用類別路徑或模組路徑中的組態檔案。當
experimental-omit-config-from-classpath
新增至代理程式選項字串時,會掃描執行中應用程式的類別路徑和模組路徑,以尋找META-INF/native-image/**/*.json
組態檔案。 - 透過使用
config-to-omit=<path>
將代理程式明確指向現有的組態檔案目錄。
使用代理程式產生條件式組態 #
代理程式可以使用啟發式方法,根據使用者指定的類別產生具有可達性條件的組態。代理程式會追蹤組態來源,並嘗試自動推斷條件。使用者類別是透過代理程式篩選檔案指定的 (如需格式的詳細資訊,請參閱 更多關於代理程式的資訊)。此外,產生的組態可以使用另一個篩選檔案進一步篩選。
目前,此功能支援兩種模式
- 在單次使用代理程式時產生條件式組態。
- 從多次使用代理程式產生條件式組態,並最終合併收集到的資料。
在代理程式執行期間產生條件式組態 #
若要啟用此模式,請將 experimental-conditional-config-filter-file=<path>
新增至代理程式的命令列,其中 <path>
指向代理程式篩選檔案。此篩選器認為包含的類別將被指定為使用者程式碼類別。若要進一步篩選產生的組態,您可以使用 conditional-config-class-filter-file=<path>
,其中 <path>
是代理程式篩選檔案的路徑。
從多次代理程式執行產生條件式組態 #
條件式組態可以從多次代理程式執行產生,這些執行會到達應用程式中不同的程式碼路徑。每次代理程式執行都會產生帶有中繼資料的組態。然後,使用 native-image-configure
來合併收集到的資料,並產生條件式組態。若要在此模式下執行代理程式,請將 experimental-conditional-config-part
新增至代理程式的命令列。一旦所有代理程式執行都完成,您可以透過呼叫來產生條件式組態
native-image-configure generate-conditional --user-code-filter=<path-to-filter-file> --class-name-filter=<path-to-filter-file> --input-dir=<path-to-agent-run-output-1> --input-dir=<path-to-agent-run-ouput-2> ... --output-dir=<path-to-resulting-conditional-config>
其中
--user-code-filter=<path-to-filter-file>
: 指定使用者類別的代理程式篩選檔案的路徑- (可選)
--class-name-filter=<path-to-filter-file>
: 進一步篩選產生組態的代理程式篩選檔案的路徑
底層啟發式方法 #
條件是使用應用程式的呼叫樹狀結構產生的。啟發式方法的工作方式如下
- 針對每個唯一方法,建立呼叫樹狀結構中對應於該方法的所有節點的清單
- 針對每個唯一方法,如果該方法在樹狀結構中有超過一個呼叫節點
- 尋找該方法所有呼叫節點之間共用的組態
- 針對該方法的每個呼叫節點,將這些呼叫之間不共用的組態傳播到呼叫者節點
- 重複 2.,直到迭代未在呼叫樹狀結構中產生任何變更。
- 針對每個包含組態的節點,產生以該方法的類別作為條件的條件式組態項目。
此啟發式方法的主要目標是嘗試找出方法根據呼叫者 (例如,包裝 Class.forName
呼叫的方法) 建立不同組態項目的位置。這表示啟發式方法不適用於透過不同相依性產生組態的程式碼 (例如,相同的方法根據系統屬性傳回具有不同類別參數的 Class.forName
呼叫)。