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

spring 引入 groovy_spring原生


spring 引入 groovy_spring_02


解压 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/

spring 引入 groovy_java_03


spring 引入 groovy_graalvm_04


spring 引入 groovy_java_05


运行下载的 VisualStudioSetup.exe

spring 引入 groovy_spring原生_06

注意:语言包中不要勾选中文,请勾选下面的英文,否则在后续项目编译过程中可能会出现 Error: Native-image building on Windows currently only supports target architecture: AMD64 错误。

然后继续按照直至完成,结束后重启电脑(Windows 的东西就是烦)。

如下打开 “x64 Native Tools Command Prompt for VS 2022” (我的电脑是64位操作系统,所以我不能打开 x86 开头的,必须使用 x64 的

spring 引入 groovy_spring 引入 groovy_07

安装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 引入 groovy_graalvm_08

创建spring工程

使用 idea 创建,或者如下在 spring 官网上创建,组件添加 spring-native,为了验证项目运行,本例还添加了 webflux 做一个 /test/show 测试接口。

spring 引入 groovy_spring 引入 groovy_09


spring 引入 groovy_spring_10

项目整体结构如下:

spring 引入 groovy_spring_11

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.version0.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和内存处理速度有关,就算电脑再好它也不快(执行过程中电脑变卡不要惊讶)。

spring 引入 groovy_spring原生_12

运行测试

构建成功后,在项目的 target 目录中会看到对应的 exe 文件,双击即可打开运行,启动速度确实非常快!

spring 引入 groovy_spring_13


然后浏览器访问 http://localhost:8080/test/show 验证结果。

如果你只是体验 SpringNative GraalVM,记得体验完后将你的 JAVA_HOME 环境变量修改为你正常开发的 jdk,避免忘记修改导致问题。


其他问题

问题一

我使用 native-maven-plugin0.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 > 修改 > 语言包 > 去掉中文,如下图所示:

spring 引入 groovy_spring_14

spring 引入 groovy_spring原生_15

问题四

构建错误 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)