原生镜像构建配置

原生镜像支持广泛的选项来配置native-image构建器。

目录 #

嵌入配置文件 #

我们建议您通过将native-image.properties文件嵌入到项目JAR文件中来提供native-image构建器的配置。native-image构建器还将自动拾取META-INF/native-image/目录(或其任何子目录)中提供的所有配置选项,并使用它来构建native-image命令行选项。

为了避免项目组成部分使用重叠配置进行构建的情况,我们建议您在META-INF/native-image中使用子目录:从多个maven项目构建的JAR文件不会受到重叠的native-image配置的影响。例如

  • foo.jar的配置位于META-INF/native-image/foo_groupID/foo_artifactID
  • bar.jar的配置位于META-INF/native-image/bar_groupID/bar_artifactID

包含foobar的JAR文件将包含这两个配置,不会发生冲突。因此,在JAR文件中存储配置数据的推荐布局如下

META-INF/
└── native-image
    └── groupID
        └── artifactID
            └── native-image.properties

请注意,在native-image.properties文件中使用${.}将扩展到包含该确切配置文件的资源位置。如果native-image.properties文件引用其子目录内的资源,这将很有用,例如,-H:ResourceConfigurationResources=${.}/custom_resources.json。始终确保使用采用资源的选项变体,即使用-H:ResourceConfigurationResources而不是-H:ResourceConfigurationFiles。其他在此上下文中有效的选项是

  • -H:DynamicProxyConfigurationResources
  • -H:JNIConfigurationResources
  • -H:ReflectionConfigurationResources
  • -H:ResourceConfigurationResources
  • -H:SerializationConfigurationResources

通过拥有这样的可组合native-image.properties文件,构建原生可执行文件不需要在命令行上进行任何其他操作。只需运行以下命令即可

$JAVA_HOME/bin/native-image -jar target/<name>.jar

要确定构建原生可执行文件时应用了哪些配置,请使用native-image --verbose。这将显示native-image从何处获取配置来构建原生镜像构建器的最终组合配置命令行选项。

native-image --verbose -jar build/basic-app-0.1-all.jar
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/common/native-image.properties
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/buffer/native-image.properties
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/transport/native-image.properties
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/handler/native-image.properties
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/codec-http/native-image.properties
...
Executing [
    <composite configuration command line options for the image builder>
]

可以在原生镜像配置示例中找到使用META-INF/native-image中配置的典型示例。

配置文件格式 #

native-image.properties文件是一个Java属性文件,它指定了native-image的配置。支持以下属性。

Args

如果您的项目需要自定义native-image命令行选项才能正确构建,请使用此属性。例如,native-image-configure-examples/configure-at-runtime-example在其native-image.properties文件中包含Args = --initialize-at-build-time=com.fasterxml.jackson.annotation.JsonProperty$Access,以确保com.fasterxml.jackson.annotation.JsonProperty$Access类在可执行文件构建时初始化。

JavaArgs

有时需要为运行native-image构建器的JVM提供自定义选项。在这种情况下,请使用JavaArgs属性。

ImageName

此属性指定可执行文件的用户定义名称。如果没有使用ImageName,则会自动选择一个名称:* native-image -jar <name.jar> 的默认可执行文件名为<name> * native-image -cp ... fully.qualified.MainClass 的默认可执行文件名为fully.qualified.mainclass

请注意,使用ImageName不会阻止您通过命令行覆盖该名称。例如,如果foo.bar包含ImageName=foo_app:* native-image -jar foo.bar将生成可执行文件foo_app,但 * native-image -jar foo.bar application将生成可执行文件application

更改默认配置目录 #

原生镜像默认情况下将配置信息存储在用户的 домашнем каталоге:$HOME/.native-image/。要更改此默认值,请将环境变量NATIVE_IMAGE_USER_HOME设置为其他位置。例如

export NATIVE_IMAGE_USER_HOME= $HOME/.local/share/native-image

参数评估顺序 #

传递给native-image的选项是从左到右评估的。这也扩展到通过META-INF/native-image目录中的配置文件间接传递的选项。考虑一个包含native-image.properties的JAR文件的示例,其中包含Args = -H:Optimize=0。您可以通过在-cp <jar-file>之后使用-H:Optimize=2选项来覆盖JAR文件中包含的设置。

原生镜像构建的内存配置 #

native-image构建器在JVM上运行,并使用底层平台的内存管理。通常的Java命令行选项(用于垃圾回收)适用于native-image构建器。

在创建原生可执行文件期间,将创建整个应用程序的表示,以确定哪些类和方法将在运行时使用。这是一个计算密集型过程,它使用以下默认值进行内存使用

-Xss10M \
-XX:MaxRAMPercentage=<percentage based on available memory> \
-XX:GCTimeRatio=19 \
-XX:+ExitOnOutOfMemoryError \

可以通过将-J + <jvm option for memory>传递给native-image工具来更改这些默认值。

-XX:MaxRAMPercentage值决定了构建器的最大堆大小,它是根据系统的可用内存计算的。默认情况下,它最大为 32GB,可以通过例如-J-XX:MaxRAMPercentage=90.0(用于 90% 的物理内存)或-Xmx4g(用于 4GB)进行覆盖。-XX:GCTimeRatio=19 将垃圾收集总时间的目标提高到 5%,这更侧重于吞吐量,并降低了峰值 RSS。构建过程还在第一次OutOfMemoryError-XX:+ExitOnOutOfMemoryError)时退出,以便在内存压力很大的环境中提供更快的反馈。

默认情况下,native-image工具最多使用 32 个线程(但不多于可用的处理器数量)。对于自定义值,请使用--parallelism=...选项。

有关native-image工具可用的其他相关选项,请参阅命令native-image --expert-options-all的输出。

指定构建时需要定义的类型 #

结构良好的库或应用程序应该在构建原生二进制文件时自行处理Java类型的链接(确保所有可达的Java类型在构建时完全定义)。默认行为是在运行时抛出链接错误(如果发生)。但是,您可以通过指定构建时需要完全链接的类来防止不需要的链接错误。为此,请使用--link-at-build-time选项。如果在正确的上下文中使用该选项(见下文),则可以指定需要在构建时完全链接的类,而无需显式列出类和包。它的设计方式是,库只能配置自己的类,以避免对其他库造成任何副作用。您可以将该选项传递给native-image工具的命令行,将其嵌入到模块路径或类路径上的native-image.properties文件中。

根据使用该选项的方式和位置,它的行为会有所不同

  • 如果使用--link-at-build-time且没有参数,则范围内所有类都需要完全定义。如果在命令行上使用该选项且没有参数,则所有类都将被视为“link-at-build-time”类。如果在模块路径上嵌入native-image.properties文件中使用该选项且没有参数,则该模块的所有类都将被视为“link-at-build-time”类。如果在类路径上嵌入native-image.properties文件中使用--link-at-build-time选项,则将抛出以下错误
      Error: Using '--link-at-build-time' without args only allowed on module path. 'META-INF/native-image/org.mylibrary/native-image.properties' in 'file:///home/test/myapp/MyLibrary.jar' not part of module path.
    
  • 如果使用--link-at-build-time选项并带参数,例如--link-at-build-time=foo.bar.Foobar,demo.myLibrary.Name,...,则参数应为完全限定的类名或包名。当在模块路径或类路径上使用(嵌入到native-image.properties文件中)时,只能指定同一个JAR文件中定义的类和包。需要在类路径上使用的库的包需要显式列出。为了简化此过程,请使用@<prop-values-file>语法在单独的文件中自动生成包列表(或类列表)。

另一个方便的选项是--link-at-build-time-paths,它允许通过其他方式指定构建时需要完全定义的类。此变体要求参数与通过-p--module-path)或-cp--class-path)传递的参数类型相同

--link-at-build-time-paths <class search path of directories and ZIP/JAR files>

将搜索给定的条目,并将所有内部类注册为--link-at-build-time类。此选项只能在命令行上使用。

联系我们