GraalVM系统显然无法将Spring应用程序编译为本机映像.
我们可以编译Spring应用程序的一个子集 - 比如说,作为一个单独的库 - 然后使用通常的javac编译器编译的其余部分吗?
或者,如果我们从应用程序中省略一些Spring功能?
还有其他可能吗?
Séb*_*uze 49
我们(Spring 团队)刚刚发布了一篇非常详细的博客文章和一段视频,发布了Spring Native测试版,可能为这个问题提供了最新的答案。
它允许您通过 Spring Bootmvn spring-boot:build-image或gradle bootBuildImage命令使用 GraalVM 本机映像编译器将 Spring 应用程序编译为本机可执行文件,或者仅native-image通过native-image-maven-plugin.
使用它最有用的链接是start.spring.io,它现在提供 Spring Native 支持和参考文档的入门部分。
确保正确配置Spring AOT Maven 和 Gradle 插件,这些插件是为您的 Spring 应用程序获得适当本机支持所必需的。
享受!
Ole*_*jev 36
这个问题的开头陈述有点模糊,所以很难正确地解决它.
GraalVM绝对可以编译Spring应用程序.GraalVM分配与普通JDK非常相似,它包括一个javac实用程序,一个java实用程序,可以添加到路径中并正常使用.您可以设置$JAVA_HOME环境变量以指向解压缩GraalVM分发的目录,添加$JAVA_HOME/bin到路径,并使用Maven或Gradle或任何其他构建工具以您通常的方式构建Spring应用程序.
GraalVM还可以运行Spring应用程序,由自身和其他JVM编译.如果你很好奇,这里有一个Spring应用程序的例子,它不仅在GraalVM上运行,而且还使用R来使用GraalVM多语言功能可视化数据图.
现在,我想你的意思是GraalVM能够创建一些Java程序的可执行本机映像.目前,GraalVM无法创建典型Spring应用程序的本机映像.这是因为GraalVM本机映像生成过程对它可以编译的Java程序有一些限制.也许主要问题是Spring的动态类加载.
有一个spring-fu项目,一个基于功能配置的实验性Kotlin微框架,旨在测试未来Spring Boot版本的新想法,目前正在尝试通过GraalVM编译成本机图像.
与此同时,GraalVM团队正在研究如何简化将Spring应用程序编译为本机映像以及支持比目前更多的Spring应用程序.一些限制将保留,因此您将始终能够构建一个不能用作GraalVM本机映像的Spring应用程序,但也许您将能够构建也可以工作的Spring应用程序.
目前尚不清楚这些变化的确切路线图.
这是一个SpringFramework问题跟踪器票,人们可以按照它来查看开发.
正如Oleg Šelajev已经指出的那样,使用GraalVM Native Image(GraalVM 的子项目)本地编译 Spring Boot 应用程序现在是可能的,但有限制,并计划在 2020 年秋季与 Spring Framework 的 5.3 版本一起发布。随着机映像你能够实现内存占用和启动时间减少类似的优点。你用Quarkus.io得到,Micronaut等我能够从周围减少内存占用500MB,以30MB从和启动时间1.5 seconds,以0.08 seconds在一个示例项目实施一个响应式 Spring Boot Web 应用程序。
简而言之,如果您想在生产中使用该功能,则必须等待 2020 年末的最终 Spring 5.3 版本以及基于它的 Spring Boot 版本。如果您想已经开始实验性地使用该功能,您可以立即开始。
====== 2020 年 6 月 10 日更新到spring-graalvm-native 0.7.0 版本。========
以下是基本步骤(六月2020年),从最新的文档导出了的弹簧项目,实验项目弹簧graalvm本地和这个博客帖子我最近写的(步骤7,8可能是因为存在一个实现compile.shbash脚本或的帮助native-image-maven-plugin- 这两种选择解释如下):
该native-image命令稍后需要带@SpringBootApplication注释的类的完全限定类名。在您pom.xml的属性中定义它,如下所示:
<properties>
...
<start-class>io.jonashackt.springbootgraal.SpringBootHelloApplication</start-class>
</properties>
Run Code Online (Sandbox Code Playgroud)
由于 GraalVM 不支持 GCLIB 代理,因此 Spring Boot 需要使用 JDK 代理。因此,请使用proxyBeanMethods = false您的 @SpringBootApplication 类的属性:
@SpringBootApplication(proxyBeanMethods = false)
public class SpringBootHelloApplication {
...
}
Run Code Online (Sandbox Code Playgroud)
最简单的方法是使用 SDKMAN:
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install java 20.1.0.r11-grl
gu install native-image
Run Code Online (Sandbox Code Playgroud)
通过键入java -version(应列出 GraalVM)和native-image --version. 有关更多详细信息,请参阅此博客文章。
这两个步骤都是由稍后与native-image命令一起使用的 Spring Graal @AutomaticFeature 为您完成的。由于@AutomaticFeature已经在 Spring Milestones 存储库上发布,我们可以简单地向我们的pom.xml(不要忘记现在还添加 Spring Milestones 存储库,因为它现在不是通过 Maven Central 提供):
<dependencies>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-graalvm-native</artifactId>
<version>0.7.1</version>
</dependency>
...
<dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
Run Code Online (Sandbox Code Playgroud)
本质上,我们需要为native-image命令准备配置变量,然后构建应用程序,扩展 Spring Boot fat JAR 并配置类路径。我创建了一个compile.sh,它使用 bash 执行必要的步骤:
#!/usr/bin/env bash
echo "[-->] Detect artifactId from pom.xml"
ARTIFACT=$(mvn -q \
-Dexec.executable=echo \
-Dexec.args='${project.artifactId}' \
--non-recursive \
exec:exec);
echo "artifactId is '$ARTIFACT'"
echo "[-->] Detect artifact version from pom.xml"
VERSION=$(mvn -q \
-Dexec.executable=echo \
-Dexec.args='${project.version}' \
--non-recursive \
exec:exec);
echo "artifact version is '$VERSION'"
echo "[-->] Detect Spring Boot Main class ('start-class') from pom.xml"
MAINCLASS=$(mvn -q \
-Dexec.executable=echo \
-Dexec.args='${start-class}' \
--non-recursive \
exec:exec);
echo "Spring Boot Main class ('start-class') is '$MAINCLASS'"
echo "[-->] Cleaning target directory & creating new one"
rm -rf target
mkdir -p target/native-image
echo "[-->] Build Spring Boot App with mvn package"
mvn -DskipTests package
echo "[-->] Expanding the Spring Boot fat jar"
JAR="$ARTIFACT-$VERSION.jar"
cd target/native-image
jar -xvf ../$JAR >/dev/null 2>&1
cp -R META-INF BOOT-INF/classes
echo "[-->] Set the classpath to the contents of the fat jar & add the Spring Graal AutomaticFeature to the classpath"
LIBPATH=`find BOOT-INF/lib | tr '\n' ':'`
CP=BOOT-INF/classes:$LIBPATH
Run Code Online (Sandbox Code Playgroud)
现在我们已经准备好制作并最终运行native-image命令的所有东西。这是一个示例,它基于上述示例项目,实现了一个 Reactive Spring Boot Web 应用程序。这个现在很棘手,取决于你想要编译为 GraalVM Native Image 的 Spring Boot 应用程序的类型!因此,最好的方法是从spring-graal-native 项目的示例项目中获得一些灵感:
GRAALVM_VERSION=`native-image --version`
echo "[-->] Compiling Spring Boot App '$ARTIFACT' with $GRAALVM_VERSION"
time native-image \
-H:+TraceClassInitialization \
-H:Name=$ARTIFACT \
-H:+ReportExceptionStackTraces \
-Dspring.native.remove-unused-autoconfig=true \
-Dspring.native.remove-yaml-support=true \
-cp $CP $MAINCLASS;
Run Code Online (Sandbox Code Playgroud)
最后通过执行 bash 脚本./compile.sh并喝杯咖啡!这需要一些时间,具体取决于您的硬件!在我 2017 年后期的 MBP 上,示例项目大约需要 3-4 分钟。如果一切顺利,您将在/target/native-image/spring-boot-graal. 只需运行它:
./target/native-image/spring-boot-graal
Run Code Online (Sandbox Code Playgroud)
==============================
7 & 8 的替代方案:native-image-maven-plugin
除了 bash 脚本(以及描述的步骤 7 和 8),还有native-image-maven-plugin。但是,如果您真的确定如何配置native-image命令,请仅使用它- 因为它现在的执行非常麻烦(我确信到 2020 年末会有很多改进)。如果要使用插件,代替7&8的步骤如下:
由于 Spring @AutomaticFeature 在使用时不会自动探索所需的 Spring 组件native-image-maven-plugin(这是一个错误吗?),我们需要明确地添加spring-context-indexer来完成这项工作:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-indexer</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)
它创建一个target/classes/META_INF/spring.components文件,然后由本机图像编译过程选取。
为了让native-image-maven-plugin正常工作,最好为本地图像编译创建一个新的 Maven 配置文件(请参阅此 pom.xml 以获得完整的工作示例):
<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>native-image-maven-plugin</artifactId>
<version>20.1.0</version>
<configuration>
<buildArgs>-H:+TraceClassInitialization -H:+ReportExceptionStackTraces -Dspring.native.remove-unused-autoconfig=true -Dspring.native.remove-yaml-support=true</buildArgs>
<imageName>${project.artifactId}</imageName>
</configuration>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Run Code Online (Sandbox Code Playgroud)
我们需要spring-boot-maven-plugin再次添加,因为它为原生图像插件准备了必要的配置。
关键部分是buildArgs需要继承native-image命令参数的标签,如compile.sh脚本中所示。与那个相比,我们可以省略-cp $CP $MAINCLASS参数,因为插件识别包括主类本身的类路径(如果start-class设置了第 3 步中的标签,则只有后者)。<imageName>${project.artifactId}</imageName>为了使用 ourartifactId作为结果的可执行映像名称,使用是一个好主意。
现在只需通过以下方式执行 Maven 配置文件:
mvn -Pnative clean package
Run Code Online (Sandbox Code Playgroud)
如果编译成功,请使用以下命令启动您的原生 Spring Boot 应用程序:
./target/spring-boot-graal
Run Code Online (Sandbox Code Playgroud)
==============================
如果你想在像 TravisCI 这样的 CI 服务器上运行本机图像编译或使用 Docker 进行编译,我可以推荐这个答案和这篇博文。另请参阅TravisCI 上的完整编译过程。
| 归档时间: |
|
| 查看次数: |
8057 次 |
| 最近记录: |