赞
踩
GraalVM Native Image学习记笔
目录
3.2 使用Native Build Tools(本机构建工具)进行测试
GraalVM参考文档的Native Image Compatibility Guide部分提供了有关GraalVM限制的更多详细信息。
Native Image Compatibility Guide
典型的Spring Boot应用程序是动态的,配置是在运行时执行的。事实上,Spring Boot自动配置的概念在很大程度上取决于对运行时状态的反应,以便正确配置。尽管可以告诉GraalVM应用程序的这些动态方面,但这样做会抵消静态分析的大部分好处。因此,当使用Spring Boot创建本机映像时,假设是一个封闭的世界,并且应用程序的动态方面受到限制。
SpringBoot本地编译限制:
不支持Spring@Profile注释和特定于配置文件的配置
不支持创建bean时更改的Properties(例如@ConditionalOnProperty和.enable Properties)
当这些限制是明确的,GraalV在构建Spring时提前处理, 通过AOT处理通常会生成:
Spring应用程序由Spring Beans组成。在内部,Spring Framework使用两个不同的概念来管理bean。有一些bean实例,它们是已经创建的实际实例,可以注入到其他bean中。还有一些bean定义,用于定义bean的属性以及应该如何创建其实例。
假设我们定义一个 @Configuration注解类,并在下面的代码中使用了它:
- @Configuration(proxyBeanMethods = false)
- public class MyConfiguration
- {
- @Bean public MyBean myBean() {
- return new MyBean();
- }
- }
bean定义是通过解析@Configuration类并找到@bean方法来创建的。在上面的例子中,我们为一个名为myBean的单例bean定义了BeanDefinition。我们还在为MyConfiguration类本身创建一个BeanDefinition。
当需要myBean实例时,Spring知道它必须调用myBean()方法并使用结果。当在JVM上运行时,当应用程序启动并且使用反射调用@Bean方法时,就会进行@Configuration类解析。
在创建本地映像时,Spring以不同的方式进行操作。它不是在运行时解析@Configuration类并生成bean定义,而是在构建时进行。一旦发现了bean定义,就会对其进行处理并将其转换为源代码,GraalVM编译器可以对其进行分析。
Spring AOT进程会将上面的配置类转换为如下代码:
- import org.springframework.beans.factory.aot.BeanInstanceSupplier;
- import org.springframework.beans.factory.config.BeanDefinition;
- import org.springframework.beans.factory.support.RootBeanDefinition;
-
- /**
- * Bean definitions for {@link MyConfiguration}.
- */
- public class MyConfiguration__BeanDefinitions {
-
- /**
- * Get the bean definition for 'myConfiguration'.
- */
- public static BeanDefinition getMyConfigurationBeanDefinition() {
- Class<?> beanType = MyConfiguration.class;
- RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
- beanDefinition.setInstanceSupplier(MyConfiguration::new);
- return beanDefinition;
- }
-
- /**
- * Get the bean instance supplier for 'myBean'.
- */
- private static BeanInstanceSupplier<MyBean> getMyBeanInstanceSupplier() {
- return BeanInstanceSupplier.<MyBean>forFactoryMethod(MyConfiguration.class, "myBean")
- .withGenerator((registeredBean) -> registeredBean.getBeanFactory().getBean(MyConfiguration.class).myBean());
- }
-
- /**
- * Get the bean definition for 'myBean'.
- */
- public static BeanDefinition getMyBeanBeanDefinition() {
- Class<?> beanType = MyBean.class;
- RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
- beanDefinition.setInstanceSupplier(getMyBeanInstanceSupplier());
- return beanDefinition;
- }
- }
Note1:
据bean定义的性质,生成的确切代码可能会有所不同。
可以在上面看到,生成的代码创建了与@Configuration类等效的bean定义,但这是GraalVM可以理解的直接方式。
myConfigurationbean有一个bean定义,myBean也有一个定义。当需要myBean实例时,会调用BeanInstanceSupplier。此供应商将调用myConfigurationbean上的myBean()方法。
Note2:
在Spring AOT处理过程中,应用程序会启动,并会指向那些可用的ben。Bean实例不是在AOT处理阶段创建的。
Spring AOT将为所有bean定义生成这样的代码。它还将在需要bean后处理时生成代码(例如,调用@Autowired方法)。还将生成ApplicationContextInitializer,当AOT处理的应用程序实际运行时,Spring Boot将使用它来初始化ApplicationContext。
尽管AOT生成的源代码可能很冗长,但它可读性很强,在调试应用程序时也很有帮助。当使用Maven和带有Gradle的build/regenerated/aotSources时,可以在target/spring aot/main/sources中找到生成的源文件。
除了生成源文件外,Spring AOT引擎还将生成GraalVM使用的提示文件。提示文件包含JSON数据,这些数据描述GraalVM应该如何处理它无法通过直接检查代码来理解的事情。
例如,可能正在私有方法上使用Spring注释。Spring将需要使用反射来调用私有方法,即使在GraalVM上也是如此。当出现这种情况时,Spring可以编写一个反射提示,以便GraalVM知道,即使不直接调用私有方法,它仍然需要在本机映像中可用。
提示文件是在META-INF/本地映像下生成的,GraalVM会自动拾取这些文件。
当使用Maven和带有Gradle的build/regenerated/aotResources时,可以在target/spring aot/main/resources中找到生成的提示文件。
Spring有时需要生成代理类来增强编写的具有附加功能的代码。为此,它使用了cglib库,该库直接生成字节码。
当应用程序在JVM上运行时,代理类会随着应用程序的运行而动态生成。创建本机映像时,需要在构建时创建这些代理,以便GraalVM可以包含这些代理。
与源代码生成不同,生成的字节码在调试应用程序时并没有特别的帮助。然而,如果需要使用javap等工具检查.class文件的内容,可以在Maven的target/spring aot/main/classes和Gradle的build/regenerated/aotClasses中找到它们。
现在我们已经很好地概述了GraalVM Native Images以及Spring提前引擎的工作原理,我们可以看看如何创建应用程序。
构建Spring Boot本机映像应用程序主要有两种方法:
Note1:
启动新的本机Spring Boot项目的最简单方法是转到start.Spring.io,添加“GraalVM native Support”依赖项并生成项目。包含的HELP.md文件将提供入门提示。
我们需要一个可以用来创建本地映像的示例应用程序。就我们的目的而言,“入门.html”部分介绍的简单的“Hello World!”web应用程序就足够了。
概括一下,我们的主要应用程序代码如下所:
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- @RestController
- @SpringBootApplication
- public class MyApplication {
-
- @RequestMapping("/")
- String home() {
- return "Hello World!";
- }
-
- public static void main(String[] args) {
- SpringApplication.run(MyApplication.class, args);
- }
- }
该应用程序使用Spring MVC和嵌入式Tomcat,这两种应用程序都经过测试和验证,可以使用GraalVM本机映像。
Spring Boot支持对Maven和Gradle的本地imaeg的直接构建。这意味着只需键入一个命令,就可以在本地运行的Docker守护进程中快速获得一个合理的image。生成的image不包含JVM,而是静态编译本机image。这会导致image变小。
Note1:
用于image的构建器是:paketobuildpacks/builder:tiny。它具有体积小,轻量级特点,但如果需要,也可以使用paketobuildpacks/builder:base或paketobbuildpacks/builder:full在imags中提供更多工具。
应该安装docker。有关更多详细信息,请参阅Get-Docker。如果在Linux上,请将其配置为允许非root用户。
Note1:
可以运行docker-run-helloworld(不带sudo)来检查docker守护进程是否可以按预期访问。查看Maven或Gradle Spring Boot插件文档以了解更多详细信息。
在macOS上,建议将分配给Docker的内存增加到至少8GB,并可能增加更多CPU。有关更多详细信息,请参阅此堆栈溢出答案。在Microsoft Windows上,请确保启用Docker WSL 2后端以获得更好的性能。
要使用Maven构建本地映像容器,应该确保pom.xml文件使用spring-boot-starter父文件和org.graalvm.buildtools:native Maven插件。应该有一个部分,如下所示:
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>3.0.5</version>
- </parent>
此外,应该在<build><plugins>部分中有这样的内容:
- <plugin>
- <groupId>org.graalvm.buildtools</groupId>
- <artifactId>native-maven-plugin</artifactId>
- </plugin>
spring-boot-starter父级声明一个本机配置文件,该配置文件配置创建本机映像所需运行的执行。你可以使用命令行上的-P标志激活配置文件。
如果你不想使用spring-boot starter父级,你需要从spring-boot的插件中为进程aot目标和从Native Build Tools插件中为添加可达性元数据目标配置执行。
要构建映像,可以在本机配置文件处于活动状态的情况下运行spring-boot:build映像目标:
$ mvn -Pnative spring-boot:build-image
当应用GraalVM Native Image插件时,Spring Boot Gradle插件会自动配置AOT任务。应该检查的Gradle构建是否包含一个插件块,其中包含 org.graalvm.buildtools.native。
只要应用了org.graalvm.buildtools.native插件,bootBuildImage任务就会生成一个本地映像,而不是JVM映像。可以使用以下方法运行任务:
$ gradle bootBuildImage
一旦运行了相应的构建命令,Docker镜像就应该可用了。可以使用docker run启动应用程序:
$ docker run --rm -p 8080:8080 docker.io/library/myproject:0.0.1-SNAPSHOT
___ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.0.5) ....... . . . ....... . . . (log output here) ....... . . . ........ Started MyApplication in 0.08 seconds (process running for 0.095)
启动时间因机器而异,但应该比JVM上运行的Spring Boot应用程序快得多。
如果打开一个web浏览器到localhost:8080,应该会看到以下输出:
你好,世界!
要正常退出应用程序,请按ctrl-c。
如果想在不使用Docker的情况下直接生成本机可执行文件,可以使用GraalVM本机构建工具。Native Build Tools是GraalVM为Maven和Gradle提供的插件。可以使用它们来执行各种GraalVM任务,包括生成本地映像。
要使用本机构建工具构建本机映像,需要在机器上安装GraalVM分发版。可以在Liberica Native Image Kit页面上手动下载,也可以使用SDKMAN!这样的下载管理器!。
$ sdk install java 22.3.r17-nik $ sdk use java 22.3.r17-nik
通过检查java-version的输出,验证是否配置了正确的版本:
- $ java -version
- openjdk version "17.0.5" 2022-10-18
- LTS OpenJDK Runtime Environment
- GraalVM 22.3.0 (build 17.0.5+8-LTS)
- OpenJDK 64-Bit Server
- VM GraalVM 22.3.0 (build 17.0.5+8-LTS, mixed mode)
在Windows上,按照以下说明安装版本22.3中的GraalVM或Liberica Native Image Kit、Visual Studio构建工具和Windows SDK。由于与Windows相关的命令行最大长度,请确保使用x64 Native Tools命令提示符而不是常规的Windows命令行来运行Maven或Gradle插件。
与buildpack支持一样,需要确保使用spring-boot-starter-parent来继承本机profile文件,并且使用org.graalvm.buildtools:native-maven插件。
在激活本机profile文件的情况下,可以调用native:compile目标来触发本机映像编译:
$ mvn -Pnative native:compile
可以在目标目录中找到本机映像可执行文件。
当Native Build Tools Gradle插件应用于的项目时,Spring Boot Gradle插件将自动触发Spring AOT引擎。任务依赖项是自动配置的,因此只需运行标准的nativeCompile任务即可生成本地映像:
$ gradle nativeCompile
本机映像可执行文件可以在build/nature/natureCompile目录中找到。
此时,的应用程序应该可以工作了。现在,可以通过直接运行应用程序来启动它:
Maven
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.0.5) ....... . . . ....... . . . (log output here) ....... . . . ........ Started MyApplication in 0.08 seconds (process running for 0.095)
启动时间因机器而异,但应该比JVM上运行的Spring Boot应用程序快得多。
如果打开一个web浏览器到localhost:8080,应该会看到以下输出:
你好,世界!
要正常退出应用程序,请按ctrl-c。
在编写本机images应用程序时,我们建议尽可能继续使用JVM来开发大部分单元和集成测试。这将有助于降低开发人员的构建时间,并允许使用现有的IDE集成。通过对JVM的广泛测试覆盖,可以将本机images测试集中在可能不同的领域。
对于本机images测试,通常希望确保以下方面有效:
当Spring Boot应用程序运行时,它会尝试检测它是否作为本机映像运行。如果它作为本机映像运行,它将使用Spring AOT引擎在构建时生成的代码初始化应用程序。
如果应用程序在常规JVM上运行,那么任何AOT生成的代码都将被忽略。
由于本机映像编译阶段可能需要一段时间才能完成,因此有时在JVM上运行应用程序是很有用的,但要让它使用AOT生成的初始化代码。这样做可以帮助快速验证AOT生成的代码中没有错误,并且在应用程序最终转换为本机映像时不会丢失任何内容。
要在JVM上运行Spring Boot应用程序并使其使用AOT生成的代码,可以将Spring.AOT.enabled系统属性设置为true。
$ java -Dspring.aot.enabled=true -jar myapplication.jar
注意:
需要确保正在测试的jar包含AOT生成的代码。对于Maven来说,这意味着应该使用-Pnative进行构建以激活本机概要文件。对于Gradle,需要确保的构建包含org.graalvm.buildtools.native插件。
如果你的应用程序在启动时将spring.aot.enabled属性设置为true,那么你就更有信心在转换为本机映像时它会工作。
你还可以考虑针对正在运行的应用程序运行集成测试。例如,可以使用SpringWebClient来调用应用程序REST端点。或者可以考虑使用Selenium这样的项目来检查应用程序的HTML响应。
GraalVM本机构建工具包括在本机映像中运行测试的功能。当你想深入测试应用程序的内部是否在GraalVM本机映像中工作时,这可能会很有帮助。
生成包含要运行的测试的本机images可能是一项耗时的操作,因此大多数开发人员可能更喜欢在本地使用JVM。然而,作为CI管道的一部分,它们可能非常有用。例如,你可以选择每天运行一次本机测试。
Spring Framework包括对运行测试的AOT支持。所有常见的Spring测试功能都可以使用本机iamges测试。例如,你可以继续使用@SpringBootTest注释。你也可以使用 Spring Boot test slices来只测试应用程序的特定部分。
Spring Framework的本机测试支持以以下方式工作:
要使用Maven运行本机测试,请确保pom.xml文件使用spring-boot-starter父级,你应该有一个部分,如下所示:
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>3.0.5</version>
- </parent>
spring-boot-starter父级声明了一个nativeTest配置文件,该配置文件配置运行本机测试所需的执行。你可以使用命令行上的-P标志激活配置文件。
提醒:
如果你不想使用spring-boot-starter-parent,你需要从spring-boot插件中为process-test-aot和Native Build Tools插件中为测试目标配置执行。
要构建images并运行测试,请在nativeTest配置文件处于活动状态的情况下使用测试目标:
$ gradle nativeTest
Spring AOT引擎会自动创建反射配置文件。但是,非内部类的嵌套配置properties必须用@NestedConfigurationProperty进行注释,否则将无法检测到它们,也无法绑定。
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.boot.context.properties.NestedConfigurationProperty;
-
- @ConfigurationProperties(prefix = "my.properties")
- public class MyProperties {
-
- private String name;
-
- @NestedConfigurationProperty
- private final Nested nested = new Nested();
-
- public String getName() {
- return this.name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Nested getNested() {
- return this.nested;
- }
- }
其中Nested是:
- public class Nested {
- private int number;
-
- public int getNumber() {
- return this.number;
- }
-
- public void setNumber(int number) {
- this.number = number;
- }
- }
上面的示例为my.properties.name和my.proporties.nested.number生成配置财产。如果嵌套字段上没有 @NestedConfigurationProperty 注释,my.propropertiex.nested_number 属性将无法在本机映像中绑定。
使用构造函数绑定时,必须使用@NestedConfigurationProperty对字段进行注释:
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.boot.context.properties.NestedConfigurationProperty;
-
- @ConfigurationProperties(prefix = "my.properties")
- public class MyPropertiesCtor {
-
- private final String name;
-
- @NestedConfigurationProperty
- private final Nested nested;
-
- public MyPropertiesCtor(String name, Nested nested) {
- this.name = name;
- this.nested = nested;
- }
-
- public String getName() {
- return this.name;
- }
-
- public Nested getNested() {
- return this.nested;
- }
- }
使用记录时,必须使用 @NestedConfigurationProperty 对参数进行注释:
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.boot.context.properties.NestedConfigurationProperty;
-
- @ConfigurationProperties(prefix = "my.properties")
- public record MyPropertiesRecord(String name, @NestedConfigurationProperty Nested nested) {
-
- }
使用Kotlin时,需要使用@NestedConfigurationProperty注释数据类的参数:
- import org.springframework.boot.context.properties.ConfigurationProperties
- import org.springframework.boot.context.properties.NestedConfigurationProperty
-
- @ConfigurationProperties(prefix = "my.properties")
- data class MyPropertiesKotlin(
- val name: String,
- @NestedConfigurationProperty val nested: Nested
- )
注意:
请在所有情况下使用public getter和setter,否则proporties将不可绑定。
只要jar包含AOT生成的资产,就可以将Spring Boot可执行jar转换为本地iamge。这可能是有用的,原因有很多,包括:
你可以使用Cloud native Buildpacks或GraalVM附带的本地iamge工具将Spring Boot可执行jar转换为本地映iamge。
注意:
你的可执行jar必须包括AOT生成的资产,如生成的类和JSON提示文件。
SpringBoot应用程序通常通过Maven(mvn-Spring-Boot:build-image)或Gradle(Gradle-bootBuildImage)集成使用云原生构建包。你也可以使用pack将经过AOT处理的Spring Boot可执行jar转换为本地 container image.。
首先,确保有一个Docker守护进程可用(有关更多详细信息,请参阅Get-Docker)。如果你在Linux上,请将其配置为允许非root用户。
你还需要按照buildpacks.io上的安装指南安装pack。
假设构建为myproject-0.0.1-SNAPSHOT.jar的经过AOT处理的Spring Boot可执行jar在目标目录中,则运行:
- $ pack build --builder paketobuildpacks/builder:tiny \
- --path target/myproject-0.0.1-SNAPSHOT.jar \
- --env 'BP_NATIVE_IMAGE=true' \
- my-application:0.0.1-SNAPSHOT
注意:
你不需要安装本地GraalVM就可以以这种方式生成映像。
打包完成后,你可以使用docker run启动应用程序:
$ docker run --rm -p 8080:8080 docker.io/library/myproject:0.0.1-SNAPSHOT
将经过AOT处理的Spring Boot可执行文件jar转换为本机可执行文件的另一个选项是使用GraalVM本机映像工具。为了实现这一点,你需要在机器上安装GraalVM分发版。你可以在Liberica Native Image Kit页面上手动下载,也可以使用SDKMAN这样的下载管理器。
假设构建为 myproject-0.0.1-SNAPSHOT.jar 的经过AOT处理的Spring Boot可执行jar在目标目录中,则运行:
- $ rm -rf target/native
- $ mkdir -p target/native
- $ cd target/native
- $ jar -xvf ../myproject-0.0.1-SNAPSHOT.jar
- $ native-image -H:Name=myproject @META-INF/native-image/argfile -cp .:BOOT-INF/classes:`find BOOT-INF/lib | tr '\n' ':'`
- $ mv myproject ../
注意:
上面命令适用于Linux或macOS机器,如果要在Windows运行,需要自己适应。
@META-INF/nature image/argfile可能没有打包在jar中。只有当需要覆盖可达性元数据时,才会包含它。
警告:
nativ-image -cp标志不接受通配符。你需要确保列出了所有的jar(上面的命令使用find和tr来执行此操作)。
GraalVM native-image Tracing Agent允许你截获JVM上的反射、资源或代理使用情况,以便生成相关提示。Spring应该自动生成大多数提示,但可以使用Tracing Agent快速识别丢失的条目。
当使用代理为本地映像生成提示时,有几种方法:
当Spring无法识别库或行为时,第一个选项有助于识别丢失的提示。
第二个选项听起来对可重复的设置更具吸引力,但默认情况下,生成的提示将包括测试基础设施所需的任何内容。当应用程序真正运行时,其中一些将是不必要的。为了解决这个问题,代理支持一个访问筛选器文件,该文件将导致某些数据从生成的输出中被排除。
使用以下命令启动连接了本机图像跟踪代理的应用程序:
- $ java -Dspring.aot.enabled=true \
- -agentlib:native-image-agent=config-output-dir=/path/to/config-dir/ \
- -jar target/myproject-0.0.1-SNAPSHOT.jar
现在,你可以练习想要提示的代码路径,然后使用ctrl-c停止应用程序。
在应用程序关闭时,native image tracing agetn会将提示文件写入给定的配置输出目录。你可以手动检查这些文件,也可以将它们用作native image构建过程的输入。要将它们用作输入,请将它们复制到src/main/resources/META-INF/nature image/目录中。下次构建本机映像时,GraalVM将考虑这些文件。
可以在native iamge tracing agent 代理上设置更高级的选项,例如通过调用程序类过滤录制的提示等。有关进一步的阅读,请参阅官方文档。
如果你需要为反射、资源、序列化、代理使用等提供自己的提示,你可以使用RuntimeHintsRegisterAPI。创建一个实现RuntimeHintsRegistrar接口的类,然后对提供的RuntimeHints实例进行适当的调用:
- import java.lang.reflect.Method;
- import org.springframework.aot.hint.ExecutableMode;
- import org.springframework.aot.hint.RuntimeHints;
- import org.springframework.aot.hint.RuntimeHintsRegistrar;
- import org.springframework.util.ReflectionUtils;
-
- public class MyRuntimeHints implements RuntimeHintsRegistrar {
-
- @Override
- public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
- // Register method for reflection
- Method method = ReflectionUtils.findMethod(MyClass.class, "sayHello", String.class);
- hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
-
- // Register resources
- hints.resources().registerPattern("my-resource.txt");
-
- // Register serialization
- hints.serialization().registerType(MySerializableClass.class);
-
- // Register proxy
- hints.proxies().registerJdkProxy(MyInterface.class);
- }
- }
然后,你可以在任何 @Configuration 类(例如你的@SpringBootApplication注释的应用程序类)上使用 @ImportRuntimeHints 来激活这些提示。
如果你有需要绑定的类(在序列化或反序列化JSON时最需要),则可以在任何bean上使用@RegisterReflectionForBinding。大多数提示都是自动推断的,例如,当接受或返回@RestController方法的数据时。但是,当您直接使用WebClient或RestTemplate时,你可能需要使用@RegisterReflectionForBinding。
RuntimeHintsPredicates API可用于测试提示。API提供了构建测试的方法,该方法可用于测试RuntimeHints实例。
如果你使用的是AssertJ,那么你的测试将如下所示:
- import org.junit.jupiter.api.Test;
-
- import org.springframework.aot.hint.RuntimeHints;
- import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
- import org.springframework.boot.docs.nativeimage.advanced.customhints.MyRuntimeHints;
-
- import static org.assertj.core.api.Assertions.assertThat;
-
- class MyRuntimeHintsTests {
-
- @Test
- void shouldRegisterHints() {
- RuntimeHints hints = new RuntimeHints();
- new MyRuntimeHints().registerHints(hints, getClass().getClassLoader());
- assertThat(RuntimeHintsPredicates.resource().forResource("my-resource.txt")).accepts(hints);
- }
- }
GraalVM native image是一种不断发展的技术,并非所有库都提供支持。GraalVM社区通过为尚未发布自己的项目提供可达性元数据来提供帮助。Spring本身不包含第三方库的提示,而是依赖于可达性元数据项目。
如果你在为Spring Boot应用程序生成native image 时遇到问题,请查看Spring Boot wiki的Spring Boot with GraalVM页面。你还可以向GitHub上的spring-aot-smoke-tests项目提交问题,该项目用于确认常见的应用程序类型是否按预期工作。
如果您发现一个库不适用于GraalVM,请提出可达性元数据项目的问题。
如果你想了解更多关于我们的构建插件提供的提前处理的信息,请参阅Maven和Gradle插件文档。要了解有关用于执行处理的API的更多信息,请浏览Spring Framework源代码的org.springframework.aot.generate和org.springfframework.beans.factory.aot包。
有关Spring和GraalVM的已知限制,请参阅Spring Boot wiki。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。