實驗性代理程式選項

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> 將代理程式明確指向現有的組態檔案目錄。

使用代理程式產生條件式組態 #

代理程式可以使用啟發式方法,根據使用者指定的類別產生具有可達性條件的組態。代理程式會追蹤組態來源,並嘗試自動推斷條件。使用者類別是透過代理程式篩選檔案指定的 (如需格式的詳細資訊,請參閱 更多關於代理程式的資訊)。此外,產生的組態可以使用另一個篩選檔案進一步篩選。

目前,此功能支援兩種模式

  1. 在單次使用代理程式時產生條件式組態。
  2. 從多次使用代理程式產生條件式組態,並最終合併收集到的資料。

在代理程式執行期間產生條件式組態 #

若要啟用此模式,請將 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>: 進一步篩選產生組態的代理程式篩選檔案的路徑

底層啟發式方法 #

條件是使用應用程式的呼叫樹狀結構產生的。啟發式方法的工作方式如下

  1. 針對每個唯一方法,建立呼叫樹狀結構中對應於該方法的所有節點的清單
  2. 針對每個唯一方法,如果該方法在樹狀結構中有超過一個呼叫節點
    • 尋找該方法所有呼叫節點之間共用的組態
    • 針對該方法的每個呼叫節點,將這些呼叫之間不共用的組態傳播到呼叫者節點
  3. 重複 2.,直到迭代未在呼叫樹狀結構中產生任何變更。
  4. 針對每個包含組態的節點,產生以該方法的類別作為條件的條件式組態項目。

此啟發式方法的主要目標是嘗試找出方法根據呼叫者 (例如,包裝 Class.forName 呼叫的方法) 建立不同組態項目的位置。這表示啟發式方法不適用於透過不同相依性產生組態的程式碼 (例如,相同的方法根據系統屬性傳回具有不同類別參數的 Class.forName 呼叫)。

延伸閱讀 #

與我們聯繫