原生映像檔建置輸出

您將在此找到有關 GraalVM 原生映像檔建置輸出的資訊。以下是建置 HelloWorld 類別的原生可執行檔時的範例輸出。

================================================================================
GraalVM Native Image: Generating 'helloworld' (executable)...
================================================================================
[1/8] Initializing...                                            (2.8s @ 0.15GB)
 Java version: 20+34, vendor version: GraalVM CE 20-dev+34.1
 Graal compiler: optimization level: 2, target machine: x86-64-v3
 C compiler: gcc (linux, x86_64, 12.2.0)
 Garbage collector: Serial GC (max heap size: 80% of RAM)
--------------------------------------------------------------------------------
 Build resources:
 - 13.24GB of memory (42.7% of 31.00GB system memory, determined at start)
 - 16 thread(s) (100.0% of 16 available processor(s), determined at start)
[2/8] Performing analysis...  [****]                             (4.5s @ 0.54GB)
    3,163 reachable types   (72.5% of    4,364 total)
    3,801 reachable fields  (50.3% of    7,553 total)
   15,183 reachable methods (45.5% of   33,405 total)
      957 types,    81 fields, and   480 methods registered for reflection
       57 types,    55 fields, and    52 methods registered for JNI access
        4 native libraries: dl, pthread, rt, z
[3/8] Building universe...                                       (0.8s @ 0.99GB)
[4/8] Parsing methods...      [*]                                (0.6s @ 0.75GB)
[5/8] Inlining methods...     [***]                              (0.3s @ 0.32GB)
[6/8] Compiling methods...    [**]                               (3.7s @ 0.60GB)
[7/8] Laying out methods...   [*]                                (0.8s @ 0.83GB)
[8/8] Creating image...       [**]                               (3.1s @ 0.58GB)
   5.32MB (24.22%) for code area:     8,702 compilation units
   7.03MB (32.02%) for image heap:   93,301 objects and 5 resources
   8.96MB (40.83%) for debug info generated in 1.0s
 659.13kB ( 2.93%) for other data
  21.96MB in total
--------------------------------------------------------------------------------
Top 10 origins of code area:            Top 10 object types in image heap:
   4.03MB java.base                        1.14MB byte[] for code metadata
 927.05kB svm.jar (Native Image)         927.31kB java.lang.String
 111.71kB java.logging                   839.68kB byte[] for general heap data
  63.38kB org.graalvm.nativeimage.base   736.91kB java.lang.Class
  47.59kB jdk.proxy1                     713.13kB byte[] for java.lang.String
  35.85kB jdk.proxy3                     272.85kB c.o.s.c.h.DynamicHubCompanion
  27.06kB jdk.internal.vm.ci             250.83kB java.util.HashMap$Node
  23.44kB org.graalvm.sdk                196.52kB java.lang.Object[]
  11.42kB jdk.proxy2                     182.77kB java.lang.String[]
   8.07kB jdk.graal.compiler             154.26kB byte[] for embedded resources
   1.39kB for 2 more packages              1.38MB for 884 more object types
--------------------------------------------------------------------------------
Recommendations:
 HEAP: Set max heap for improved and more predictable memory usage.
 CPU:  Enable more CPU features with '-march=native' for improved performance.
--------------------------------------------------------------------------------
    0.8s (4.6% of total time) in 35 GCs | Peak RSS: 1.93GB | CPU load: 9.61
--------------------------------------------------------------------------------
Build artifacts:
 /home/janedoe/helloworld/helloworld (executable)
 /home/janedoe/helloworld/helloworld.debug (debug_info)
 /home/janedoe/helloworld/sources (debug_info)
================================================================================
Finished generating 'helloworld' in 17.0s.

建置階段 #

初始化 #

在此階段,將設定原生映像檔建置流程,並初始化 Features

原生映像檔種類

預設情況下,原生映像檔會產生可執行檔,但它也可以產生原生共用程式庫靜態可執行檔

Java 版本資訊

原生映像檔流程的 Java 和供應商版本。兩者也用於產生的原生二進位檔中的 java.vm.versionjava.vendor.version 屬性。當您提出問題時,請回報版本和供應商。

Graal 編譯器

Graal 編譯器所選取的最佳化層級和目標機器類型。最佳化層級可以使用 -O 選項來控制,預設值為 2,這會啟用積極的最佳化。使用 -Ob 來啟用快速建置模式,這會加快編譯階段。這在開發期間有助於減少映像檔建置時間。使用 -Os 來針對大小進行最佳化。目標機器類型可以使用 -march 選項來選取,在 AMD64 上預設值為 x86-64-v3,在 AArch64 上預設值為 armv8-a。請參閱此處,以取得如何使用此選項的建議。

在 Oracle GraalVM 上,該行也會顯示有關設定檔導向最佳化 (PGO)的資訊。

  • off:未使用 PGO
  • instrument:產生的可執行檔或共用程式庫已檢測,以收集 PGO 的資料 (--pgo-instrument)
  • user-provided:已啟用 PGO,並使用使用者提供的設定檔 (例如 --pgo default.iprof)
  • ML-inferred:機器學習 (ML) 模型用於靜態推斷控制分割分支的設定檔。

C 編譯器

原生映像檔建置流程所使用的 C 編譯器可執行檔、供應商、目標架構和版本資訊。

垃圾收集器

產生之可執行檔中使用的垃圾收集器

  • 序列 GC 是預設的 GC,並針對低記憶體佔用空間和小型 Java 堆積大小進行最佳化。
  • G1 GC (在 GraalVM 社群版中無法使用) 是一種多執行緒 GC,經過最佳化可減少停止世界暫停,並因此在實現高輸送量的同時改善延遲。
  • Epsilon GC 不執行任何垃圾收集,並且專為僅配置少量記憶體的非常短暫執行的應用程式設計。

如需更多資訊,請參閱記憶體管理文件

最大堆積大小

預設情況下,堆積大小限制為系統記憶體的特定百分比,允許垃圾收集器根據其原則自由配置記憶體。當您叫用原生可執行檔時,請使用 -Xmx 選項 (例如,針對 64MB 使用 ./myapp -Xmx64m) 來限制最大堆積大小,以獲得更低且更可預測的記憶體佔用空間。在某些情況下,這也可以改善延遲。當使用原生映像檔建置時,請使用 -R:MaxHeapSize 選項來預先設定最大堆積大小。

使用者特定功能

使用者提供或明確啟用,或隱式註冊給使用者的所有 Features,例如,透過架構。GraalVM 原生映像檔部署了許多內部功能,這些功能會從此清單中排除。

實驗性選項

所有作用中的實驗性選項的清單,包括其來源和可用的 API 選項替代方案 (如果有的話)。

應避免在生產環境中使用實驗性選項,並且可能會在任何版本中變更。如果您依賴實驗性功能並希望將選項視為穩定,請提出問題。

已選取 NATIVE_IMAGE_OPTIONS

透過 NATIVE_IMAGE_OPTIONS 環境變數選取的其他建置選項。與 JAVA_TOOL_OPTIONS 類似,環境變數的值會加到提供給 native-image 的選項之前。不允許透過 NATIVE_IMAGE_OPTIONS 傳遞引數檔案。NATIVE_IMAGE_OPTIONS 環境變數旨在由使用者、建置環境或工具使用,以插入其他建置選項。

建置資源

建置流程使用的記憶體限制和執行緒數目。

更精確地說,是 Java 堆積的記憶體限制,因此實際的記憶體消耗可能會更高。請檢查建置結束時報告的峰值 RSS,以瞭解實際使用了多少記憶體。預設情況下,建置流程會嘗試僅使用可用記憶體 (以避免對建置機器造成記憶體壓力),且永遠不超過 32GB 的記憶體。如果可用記憶體少於 8GB,則建置流程會改為使用總記憶體的 85%。因此,如果您的機器在建置期間速度緩慢,請考慮釋放記憶體,例如,關閉您不需要的應用程式。可以覆寫預設行為,例如使用 -J-XX:MaxRAMPercentage=60.0-J-Xmx16g

預設情況下,建置流程會使用所有可用的處理器來最大化速度,但不會超過 32 個執行緒。使用 --parallelism 選項來明確設定執行緒數目 (例如,--parallelism=4)。使用較少的執行緒來減少系統負載以及記憶體消耗 (以較慢的建置流程為代價)。

執行分析 #

在此階段,會執行指標分析。進度指示器會視覺化分析反覆運算的次數。大量的反覆運算可能表示分析中存在問題,這可能是由於組態錯誤或行為不當的功能所導致。

可達到的類型、欄位和方法

可達到的類型 (基本類型、類別、介面和陣列)、欄位和方法數量,與作為建置流程一部分載入的類型、欄位和方法總數相比。大量載入的但無法到達的元素可能表示組態問題。為減少額外負荷,請確保您的類別路徑和模組路徑僅包含建置應用程式所需的項目。

反射註冊

已註冊進行反射的類型、欄位和方法數量。大量可能會導致顯著的反射額外負荷、減慢建置流程並增加原生二進位檔的大小 (請參閱反射中繼資料)。

JNI 存取註冊

已註冊進行 JNI 存取的類型、欄位和方法數量。

外部函式 Stub

已註冊進行外部函式存取的向下呼叫和向上呼叫數量。

執行階段編譯方法

標記為進行執行階段編譯的方法數量。此數字僅在將執行階段編譯建置到可執行檔中時顯示,例如,在建置Truffle語言時。執行階段編譯方法會導致堆積中的圖形編碼

建置全域 #

在此階段,會建置包含所有類型、欄位和方法的全域,然後用來建立原生二進位檔。

剖析方法 #

在此階段,Graal 編譯器會剖析所有可達到的方法。進度指示器會以不斷增加的間隔定期列印。

內嵌方法 #

在此階段,會執行微不足道的方法內嵌。進度指示器會視覺化內嵌反覆運算的次數。

編譯方法 #

在此階段,Graal 編譯器會將所有可達到的方法編譯為機器碼。進度指示器會以不斷增加的間隔定期列印。

配置方法 #

在此階段,會配置編譯方法。進度指示器會以不斷增加的間隔定期列印。

建立映像檔 #

在此階段,會建立原生二進位檔並寫入磁碟。除錯資訊也會在此階段產生 (如果要求的話)。

程式碼區域

程式碼區塊包含 Graal 編譯器為所有可存取方法產生的機器碼。因此,減少可存取方法的數量也會減少程式碼區塊的大小。

程式碼區塊的來源

為了幫助使用者了解程式碼區塊中的機器碼來自何處,建置輸出會顯示主要來源的細目。來源是一組 Java 原始碼,可能是 JAR 檔案、套件名稱或類別名稱,具體取決於可用的資訊。例如,java.base 模組包含來自 JDK 的基礎類別。svm.jar 檔案、org.graalvm.nativeimage.base 模組和類似的來源包含 Native Image 執行階段的內部來源。為了減少程式碼區塊的大小,進而減少原生可執行檔的總大小,請根據程式碼區塊的細目重新評估應用程式的依賴性。某些程式庫和框架比其他程式庫和框架更適合 Native Image,而且程式庫或框架的較新版本可能會改善(或惡化)其程式碼佔用空間。

映像檔堆積

堆積包含可存取的物件,例如靜態應用程式資料、中繼資料和用於不同目的的 byte[] (如下所述)。

儲存在 byte[] 中的一般堆積資料

所有 byte[] 物件的總大小,這些物件既不用於 java.lang.String,也不用於程式碼中繼資料反射中繼資料圖形編碼。因此,這也可能包含來自應用程式程式碼的 byte[] 物件。

儲存在 byte[] 中的嵌入式資源

所有用於在原生二進位檔中儲存資源 (例如,透過 Class.getResource() 存取檔案) 的 byte[] 物件的總大小。資源的數量顯示在堆積區段中。所有資源的清單,包括其模組、名稱、來源和大小等額外資訊,都包含在建置報告中。也可以使用 -H:+GenerateEmbeddedResourcesFile 選項以 JSON 格式請求此資訊。此類 JSON 檔案會根據 embedded-resources-schema-v1.0.0.json 中定義的 JSON 結構描述進行驗證。

儲存在 byte[] 中的程式碼中繼資料

所有用於程式碼區塊中繼資料的 byte[] 物件的總大小。因此,減少可存取方法的數量也會減少此中繼資料的大小。

儲存在 byte[] 中的反射中繼資料

所有用於反射中繼資料 (包括類型、欄位、方法和建構函式資料) 的 byte[] 物件的總大小。為了減少反射中繼資料的數量,請減少註冊用於反射的元素的數量。

儲存在 byte[] 中的圖形編碼

所有用於圖形編碼的 byte[] 物件的總大小。這些編碼是執行階段編譯方法的結果。因此,減少此類方法的數量也會減少對應圖形編碼的大小。

堆積對齊

選取的垃圾收集器對齊堆積而保留的額外空間。堆積對齊也可能包含特定於 GC 的資料結構。因此,其大小只能透過切換到不同的垃圾收集器來影響。

偵錯資訊

產生的偵錯資訊的總大小 (如果已啟用)。

其他資料

二進位檔中既不在程式碼區塊中、也不在堆積中,也不在偵錯資訊中的資料量。此資料通常包含 Native Image 的內部資訊,不應佔主導地位。

安全性報告 #

此區段在 GraalVM 社群版中不可用。

還原序列化

這會顯示原生可執行檔中是否包含 Java 還原序列化。如果未包含,則會減少可執行檔的攻擊面,因為無法利用基於 Java 還原序列化的攻擊來攻擊可執行檔。

軟體組件表 (SBOM)

此區段指出是否已組裝 SBOM,以及以何種方式儲存。儲存格式包括:embed,將 SBOM 嵌入二進位檔中;classpath,將 SBOM 儲存到類別路徑;以及 export,將 SBOM 作為 JSON 建置成品包含在內。使用 --enable-sbom 啟用此功能,預設為 embed 選項。嵌入時,會顯示 SBOM 大小。永遠會顯示元件數量。

如需更多資訊,請參閱軟體組件表

向後邊緣控制流程完整性 (CFI)

可以使用實驗性的 -H:CFI=HW 選項來強制執行控制流程完整性 (CFI)。此功能目前僅適用於 Graal 為 Linux AArch64 編譯的程式碼,並利用指標驗證程式碼 (PAC) 來確保函式傳回位址的完整性。

軟體控制流程完整性 (CFI)

可以使用實驗性的 -H:CFI=SW_NONATIVE 選項以軟體方式強制執行控制流程完整性 (CFI)。此功能目前僅適用於 Graal 為 Linux AMD64 編譯的程式碼,並驗證間接分支和方法傳回的目標。

建議 #

建置輸出可能包含以下一項或多項建議,可協助您充分利用 Native Image。

AWT:抽象視窗工具組缺少可存取性中繼資料

Native Image 分析已包含來自java.awt 套件的類別,但找不到其任何可存取性中繼資料。使用追蹤代理程式為您的應用程式收集此類中繼資料。否則,您的應用程式不太可能正常運作。如果您的應用程式不是桌面應用程式 (例如直接使用 Swing 或 AWT),您可能需要重新評估是否實際需要對 AWT 的依賴性。

CPU:啟用更多 CPU 功能以提高效能

Native Image 建置程序已確定您的 CPU 支援比目前啟用的更多功能,例如 AES 或 LSE。如果您將應用程式部署在同一部機器或支援相同 CPU 功能的類似機器上,請考慮在建置時使用 -march=native。此選項允許 Graal 編譯器使用所有可用的 CPU 功能,進而可以顯著提高應用程式的效能。使用 -march=list 列出所有可以明確指定目標的可用機器類型。

G1GC:使用 G1 垃圾收集器以改善延遲和輸送量

G1 垃圾收集器適用於您的平台。請考慮在建置時使用 --gc=G1 來啟用它,以改善應用程式的延遲和輸送量。如需更多資訊,請參閱關於記憶體管理的說明文件。為了獲得最佳的尖峰效能,請考慮使用設定檔導向最佳化

HEAP:指定最大堆積大小

請參閱最大堆積大小

PGO:使用設定檔導向最佳化來提高輸送量

請考慮使用設定檔導向最佳化來最佳化您的應用程式,以提高輸送量。當 AOT 編譯應用程式時,這些最佳化允許 Graal 編譯器利用分析資訊,類似於它作為 JIT 編譯器執行時。為此,請執行以下步驟

  1. 使用 --pgo-instrument 建置您的應用程式。
  2. 使用代表性工作負載執行您的檢測應用程式,以產生 .iprof 檔案形式的分析資訊。
  3. 重新建置您的應用程式,並使用 --pgo=<your>.iprof 傳入分析資訊,以產生最佳化版本的應用程式。

相關指南:使用設定檔導向最佳化來最佳化原生可執行檔

為了獲得最佳的尖峰效能,請考慮使用G1 垃圾收集器

QBM:使用快速建置模式來加速建置

請考慮在開發期間使用快速建置模式 (-Ob) 來加速建置。更精確地說,此模式會減少 Graal 編譯器執行的最佳化次數,從而減少編譯階段的整體時間。快速建置模式不僅適用於開發,還可能導致產生的可執行檔大小較小。但是,請注意,由於最佳化次數減少,可執行檔的整體尖峰輸送量可能會較低。

INIT:使用嚴格的映像檔堆積配置

開始使用 --strict-image-heap 來減少組態量,並為未來將預設為此的 GraalVM 版本做好準備。此模式僅要求儲存在映像檔堆積中的類別使用 --initialize-at-build-time 標記。這有效地減少了實現建置階段初始化所需的組態項目數量。採用新模式時,最好從頭開始引入建置階段初始化。在此過程中,最好選取個別類別 (而不是整個套件) 以進行建置階段初始化。此外,在遷移到新旗標之前,請務必將所有框架依賴性更新到最新版本,因為它們也可能需要遷移。

請注意,從 GraalVM for JDK 22 開始,--strict-image-heap 在 Native Image 中預設為啟用。

資源使用率統計 #

垃圾收集

所有垃圾收集器中花費的總時間、總 GC 時間除以總處理時間的百分比,以及垃圾收集的總次數。大量的收集次數或在收集器中花費的時間通常表示系統處於記憶體壓力下。增加可用記憶體量以減少建置原生二進位檔的時間。

尖峰 RSS

作業系統報告的尖峰常駐集大小。此值表示建置程序消耗的最大記憶體量。您可能需要將此值與建置資源區段中報告的記憶體限制進行比較。如果還有足夠的空間,且GC 統計資料沒有顯示任何問題,則可以將系統的總記憶體量減少到接近尖峰 RSS 的值,以降低營運成本。

CPU 負載

程序使用的 CPU 時間除以總處理時間。增加 CPU 核心數量以減少建置原生二進位檔的時間。

建置成品 #

所有建置產出物的列表。這包含產生的原生二進位檔,但也可能包含其他產出物,例如額外的函式庫、C 標頭檔或除錯資訊。其中某些產出物必須與原生二進位檔保持在相同位置,因為它們在執行時期是必需的。舉例來說,對於使用 AWT 的應用程式,建置過程也會輸出 JDK 中的函式庫和墊片 (shims),以提供相容的 AWT 支援。這些函式庫需要與原生二進位檔一起複製和發佈。使用 -H:+GenerateBuildArtifactsFile 選項來指示建置器產生機器可讀的 JSON 格式建置產出物列表。此 JSON 檔案會根據 build-artifacts-schema-v0.9.0.json 中定義的 JSON Schema 進行驗證。此 Schema 也包含每個可能產出物類型的說明,並解釋它們是否在執行時期是必需的。

機器可讀的建置輸出 #

native-image 建置器產生的建置輸出是為人類設計的,可能會隨著新版本的發布而演變,因此不應以任何方式由工具進行剖析。相反地,請使用 -H:BuildOutputJSONFile=<file.json> 選項來指示建置器產生機器可讀的 JSON 格式建置輸出,例如可用於建置監控工具。此 JSON 檔案會根據 build-output-schema-v0.9.3.json 中定義的 JSON Schema 進行驗證。請注意,只有在建置成功時才會產生 JSON 檔案。

以下範例說明如何在 CI/CD 建置管道中使用此功能來檢查可到達方法的數量是否超過特定閾值

native-image -H:BuildOutputJSONFile=build.json HelloWorld
# ...
cat build.json | python3 -c "import json,sys;c = json.load(sys.stdin)['analysis_results']['methods']['reachable']; assert c < 12000, f'Too many reachable methods: {c}'"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AssertionError: Too many reachable methods: 12128

彩色建置輸出 #

預設情況下,native-image 建置器在找到適當的終端機時,會將建置輸出著色以提高可讀性。當檢查色彩支援時,它也會採用 NO_COLORCITERM 環境變數。若要明確控制彩色輸出,請將 --color 選項設定為 alwaysneverauto (預設值)。

與我們聯繫