原生镜像构建配置
原生镜像支持广泛的选项来配置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
包含foo
和bar
的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
类。此选项只能在命令行上使用。