SpringNative 目前还是 bate 版本,请注意使用,勿应用于生产!
经过 graalvm 编译打包后生产的 exe(windows)或 Linux 可执行程序,为单文件,可以随处拷贝直接运行,启动速度非常快。
本文简要的概述一个 demo 的完成过程
环境安装
1、安装和配置 maven(略)
2、下载 GraalVM (本文社区版 graalvm-ce-java17-22.1.0)
3、下载 Visual Studio Installer,Windows 打包 exe 需要 c++ 环境
官方下载地址:https://github.com/graalvm/graalvm-ce-builds/releases
解压 graalvm-ce-java17-windows-amd64-22.1.0.zip
后配置环境变量,将 JAVA_HOME
指向解压后的目录,将 %JAVA_HOME%\bin
追加到环境变量 Path 中(就是常规的 java 环境变量配置,只是把你 graalvm jdk 替代 java jdk 了)。
下载的 native-image-installable-svm-java17-windows-amd64-22.1.0.jar
文件在下面使用。
官方下载地址:https://visualstudio.microsoft.com/zh-hans/downloads/
运行下载的 VisualStudioSetup.exe
注意:语言包中不要勾选中文,请勾选下面的英文,否则在后续项目编译过程中可能会出现
Error: Native-image building on Windows currently only supports target architecture: AMD64
错误。
然后继续按照直至完成,结束后重启电脑(Windows 的东西就是烦)。
如下打开 “x64 Native Tools Command Prompt for VS 2022” (我的电脑是64位操作系统,所以我不能打开 x86 开头的,必须使用 x64 的)
安装AOT编译器 native-image
命令操作【离线方式】
gu install --file native-image-installable-svm-java17-windows-amd64-22.1.0.jar
或者在命令中直接【在线】联网按照(推荐)
gu install native-image
查看已经安装的 native-image 版本
native-image --version
截图如下:
创建spring工程
使用 idea 创建,或者如下在 spring 官网上创建,组件添加 spring-native,为了验证项目运行,本例还添加了 webflux 做一个 /test/show 测试接口。
项目整体结构如下:
pom.xml 文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-native-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-native-demo</name>
<description>SpringNative project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<repackage.classifier/>
<spring-native.version>0.12.0</spring-native.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-native</artifactId>
<version>${spring-native.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>${repackage.classifier}</classifier>
<image>
<builder>paketobuildpacks/builder:tiny</builder>
<env>
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
</env>
</image>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-aot-maven-plugin</artifactId>
<version>${spring-native.version}</version>
<executions>
<execution>
<id>test-generate</id>
<goals>
<goal>test-generate</goal>
</goals>
</execution>
<execution>
<id>generate</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<profiles>
<profile>
<id>native</id>
<properties>
<repackage.classifier>exec</repackage.classifier>
<native-buildtools.version>0.9.9</native-buildtools.version>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>${native-buildtools.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<id>test-native</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
<execution>
<id>build-native</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<!--新增配置-->
<configuration>
<!--如果希望在运行时初始化包中的类使用 initialize-at-run-time -->
<!--如果希望在构建时初始化包中的类使用 initialize-at-build -->
<buildArgs>
--initialize-at-run-time=io.netty.util.internal.logging.Log4JLogger
--initialize-at-run-time=io.netty.handler.ssl.ReferenceCountedOpenSslContext
--initialize-at-run-time=io.netty.handler.ssl.JdkNpnApplicationProtocolNegotiator
--initialize-at-run-time=io.netty.handler.ssl.JettyNpnSslEngine
--initialize-at-run-time=io.netty.handler.ssl.ConscryptAlpnSslEngine
--initialize-at-run-time=io.netty.handler.ssl.BouncyCastleAlpnSslUtils
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
默认生成的 pom 中的
native-buildtools.version
为0.9.11
我打包编译不成功,一直出现文末的错误,后来改成0.9.9
后成功。
源代码地址:https://github.com/xzxiaoshan/spring-native-demo
编译生成exe文件
还是打开 “x64 Native Tools Command Prompt for VS 2022”
在创建进行工程代码目录后执行命令 mvn clean package -DskipTests -Pnative
进行打包,然后要多等一会才能打包成功,这个打包速度也忒慢了,就一个普通 demo 就要好久,跟电脑的CPU和内存处理速度有关,就算电脑再好它也不快(执行过程中电脑变卡不要惊讶)。
运行测试
构建成功后,在项目的 target 目录中会看到对应的 exe 文件,双击即可打开运行,启动速度确实非常快!
然后浏览器访问 http://localhost:8080/test/show 验证结果。
如果你只是体验 SpringNative GraalVM,记得体验完后将你的 JAVA_HOME 环境变量修改为你正常开发的 jdk,避免忘记修改导致问题。
其他问题
问题一
我使用 native-maven-plugin
的 0.9.12
(截稿时最新)不能正常编译,报错如下(暂未找到问题原因):
Fatal error: Unsupported OptionOrigin: C:\Users\ADMINI~1\AppData\Local\Temp\native-image12860059531825023930args
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 18.721 s
[INFO] Finished at: 2022-07-07T09:21:29+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.graalvm.buildtools:native-maven-plugin:0.9.11:build (build-native) on project springnative: Execution of D:\JavaDev\jdk\graalvm-ce-java17-22.1.0\bin\native-image.cmd @C:\Users\ADMINI~1\AppData\Local\Temp\native-image12860059531825023930args returned non-zero result -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
后改成版本为 0.9.9
后成功,如有其他大佬知道问题原因和解决方法,欢迎留言指导,谢谢!
问题二
错误 native-image.cmd @target\tmp\native-image-6958951881815971903.args returned non-zero result
的解决方法为:
手工修改 native-image-6958951881815971903.args
文件里面的内容,将 \\
全部修改为 /
之后,再重新执行这个命令,该问题在 Linux 下不存在(不知插件的未来版本是否会修复这个问题)。
问题三
错误 Error: Native-image building on Windows currently only supports target architecture: AMD64
的解决方法为:
Visual Studio Installer > 修改 > 语言包 > 去掉中文,如下图所示:
问题四
构建错误 Error: Please specify class (or <module>/<mainclass>) containing the main entry point method. (see --help)
时,在 pom.xml
中将入口类配置上,如下:
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<mainClass>com.example.demograalvm.DemoGraalvmApplication</mainClass>
</configuration>
</plugin>
(END)