使用GraalVM native-image 编译SpringBoot3全过程

本文记录了使用native-image编译SpringBoot3.0.3的过程及遇到的问题。其中一些问题也是网上很多朋友遇到,我在实际操作的过程也遇到过同样的问题,在此做一记录。

目录


一、编译环境准备

1.1 安装GraalVM

它在java HotSpot JVM的基础上添加了JIT编译器和AOT来实现将应用编译成为本地可执行文件。除了java之外,GraalVM还支持JavaScript、Ruby、Python等多种编程语言。

GraalVM下载地址:https://www.oracle.com/downloads/graalvm-downloads.html。下载的时候选择对应的平台和版本。

GraalVM跟JDK一样也有两个版本,社区版和企业版本,大家可以根据需要自行选择。

如果下载的zip压缩文件,选择一个目录将它解压即可。

1.2 安装native-image

  • 方法1 : 控制台输入命令 gu install native-image即可,下载速度贼慢
  • 方法2:在github上下载对应版本的native-image安装包进行本地安装

Release GraalVM Community Edition 22.3.0 · graalvm/graalvm-ce-builds (github.com)

控制台输入命令 gu install -L 你的下载位置

安装成功,控制台输入gu list如图所示

环境变量配置:

JAVA_HOME = GraalVM的的根目录

PATH = %JAVA_HOME%\bin

1.3 IDE设置

打开项目的Project Settings,SDK—>Edit—->Add SDK 选择GraalVM。

Edit Configurations

设置Build and run 的JRE为GraalVM-17

1.4 Visual Studio 2022

由于Windows相关的命令行最大长度限制,所以需要使用x64 Native Tools Command Prompt而不是常规的Windows命令来运行maven或者Gradle插件。

安装好后需要配置Visual Studio的环境变量。

mvn -Pnative native:compile

1.5 pom.xml文件

<build>
   <plugins>
      <plugin>
         <groupId>org.graalvm.buildtools</groupId>
         <artifactId>native-maven-plugin</artifactId>
      </plugin>
      <plugin>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
   </plugins>
</build

native-maven-plugin 默认为最新版本:0.9.20

二、使用native-image工具本地编译

1、打开X64 Native Tools Command Propmt窗口执行:

mvn -Pnative native:compile

执行过程中出现下面错误信息:

Execution of E:\tools\graalvm-ce-java17-22.3.1\bin\native-image.cmd @target\tmp\native-image-2154084464642699530.args returned non-zero result

如下图:

根据错误提示我们查看并修改

F:\myworkspace\demo-test\demo\target\native-image-2154084464642699530.args

文件将里面的所有\\路径全局替换为/路径符号。

替换前:

替换后:

为什么将“\\”替换为“/”就可以成功执行,此处应该是 native-maven-plugin(0.9.20) 版本导致的,0.9.19版本也有同样的问题,在linux下应该没有此问题。

 然后我们手动执行刚才报错的命令 (重要,也就是原来一步完成的任务,现在需要两步完成)

native-image @target\tmp\native-image-2154084464642699530.args

此处我们也可以将args文件中的参数粘贴出来作为native-image 后面的参数,不需要替换路径,只需要将相关参数合并成单行命令执行也能成功,说明native-image通过vcvars64.bat脚本执行后是支持window的路径\\格式的)

等价于

执行完毕结果

本文参考:

SpringBoot3 Graalvm Native-Image尝鲜_Zyp168168的博客-CSDN博客

三、AOT技术

GraalVM Native Images是一个利用AOT(Ahead-of-Time)技术把java程序直接编译成可执行程序的编译工具,编译出来的程序在运行时不再依赖JRE,同时启动速度快,资源消耗低,这对传统java程序来说都是极大的优势。

同时云原生应用来说,GraalVM Native Images编译生成的程序体积很小,非常适合云原生环境,目前由于传统java程序生成的镜像中需要包含一个体积很大的JRE或JDK而经常被人诟病。Spring Boot从3.0版本开始支持AOT技术。

3.1 AOT与JIT

  • 在程序运行前编译,可以避免在运行时的编译性能消耗和内存消耗
  • 可以在程序运行初期就达到最高性能
  • 可以显著的加快程序的启动

3.2 缺点

  1. 程序运行时动态调整的资源无法直接使用,例如反射、动态代理等,需要在代码中通过Hint为编译器指定
  2. 应用的classpath在编译后就固定了,不能动态调整
  3. 类不会延迟加载(lazy loading),应用启动时一次性加载完成
  4. 部分java切面(AOP)技术不支持
  5. 编译时间长
  6. 牺牲了跨平台的的优势
  7. 将提前编译的内容保存会占用更多的外存

3.3 JIT优点

    顺便说一下JIT

  • 可以根据当前硬件情况实时编译生成最优机器指令(ps. AOT也可以做到,在用户使用是使用字节码根据机器情况在做一次编译)
  • 可以根据当前程序的运行情况生成最优的机器指令序列
  • 当程序需要支持动态链接时,只能使用JIT
  • 可以根据进程中内存的实际情况调整代码,使内存能够更充分的利用

3.4 JIT缺点

  • 编译需要占用运行时资源,会导致进程卡顿
  • 由于编译时间需要占用运行时间,对于某些代码的编译优化不能完全支持,需要在程序流畅和编译时间之间做权衡
  • 在编译准备和识别频繁使用的方法需要占用时间,使得初始编译不能达到最高性能

四、单元测试

传统的Spring Boot3单元测试技术仍然可以使用。需要注意的是 Spring Native不支持JUnit4,需要使用JUnit5。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年12月22日
下一篇 2023年12月22日

相关推荐