SpringBoot之GraalVM

标签: 无 分类: 未分类 创建时间:2022-08-04 03:10:30 更新时间:2024-12-03 13:01:37

1.前言

GraalVM 这是一个java虚拟机,感觉介绍来说,是新一代的java虚拟机,在内存和启动时间上,都比传统的Hotspot有了飞跃,但是目前还不成熟。看了这么多的文章,还是要上手做一下,才能知道到底是好还是不好。

2024年09月22日,我准备在 UOS Server V20 1060a 上进行镜像的打包,jdk17,springboot 3.x, 主要步骤:

  • 1.graalvm 和 maven 的环境配置
  • 2.native-image 安装
  • 3.mvn 编译打包
参考文章:
【1】.『Spring Boot 2.4新特性』减少95%内存占用 这里提到了一个 GraalVM 的高性能的虚拟机,文章发布于 2020-12-23 ,项目也是springboot 2.4,现在的发展已经很快了。
【2】.GraalVM系列(一):JVM的未来——GraalVM集成入门 发布于 2021-01-22 21:27,GraalVM是一个新的JVM,原本用于替换HotSpot的C2编译器,后来独立成JVM的一个产品,它很新但架不住对Native Image、多语言集成、高性能特性的诱惑,就连“后知后觉”的Spring也着手相关的支持工作,而新新的框架诸如quarkus、micronaut都已提供了比较好的支持。
【3】.Java 革新之路:GraalVM 原生镜像
【4】.Graalvm入门跳坑记录-SpringBoot篇 这是2021年02月的一篇文章,写了如何引入依赖,以及相关的配置
【5】.以GraalVM原生镜像的方式运行Spring Boot应用程序 这篇文章比较老了,2020年写的,现在很多的东西都要改吧。
【6】.Spring Native documentation 这是spring官方提供的一个示例,包括sdkman、graalvm的安装,但是版本目前只是0.12.1,需要springboot 2.7.1,这个还是需要继续的打磨的,本身springboot 2.7.1就是刚刚出现的新的版本。
【7】.JDK/JVM的新储君——GraalVM 那些已经在JVM扎了根的公司,GraalVM的出现无疑是有建设意义的,它的多语言环境,能让Java充当主持人的身份,舞台不再属于Java一个人,而是“你方唱罢我登场”,大家一起唱好这出戏。至于编译成二进制可执行文件,我个人感觉不是很有必要,至少大部分Java之前已经做的很好的场景其实是不需要这个二进制文件的。这个功能更像是对Java的一些补充,用于应对某些特殊的情况。
【8】.通过 GraalVM 将 Java 程序编译成本地机器码! Graal VM 的缺点:1.启动时间、内存使用确实有大幅度优化,但是对于长时间运行的大型应用,未必有 HotSpot 的 Java 应用程序速度快。
【9】.使用 GraalVM 为 Java 应用程序构建最少的 Docker 镜像 这里是GraalVM的docker构建,使用 jlink 构建自定义 JDK 分配。这篇文章其实也是说的如何使用GraalVM的docker直接构建可执行的应用程序,没有实际的测试过
【10】.Spring Native 项目,把 Spring 项目编译成原生程序!
【11】.Spring Native
【12】.Spring Native 项目,把 Spring 项目编译成原生程序! springboot 2.4.4
【13】.SpringBoot3.x原生镜像-Native Image尝鲜 SpringBoot3.x原生镜像正式发布后会是SpringBoot在云原生领域的一个巨大进步,让我们拭目以待。但是就目前来看,常用的Windows开发环境下想要尝试native image技术需要解决比较多的问题,Linux和Unix平台下尚未验证,希望后面的版本迭代能够降低使用难度并且支持一个命令多平台打包的功能。
【14】.Native Support in Spring Boot 3.0.0-M5 官方的文档如何启动spring native-image

2.安装

(1)安装 GraalVM
下载 GraalVM JDK17 linux amd 版本,解压相关的压缩包。

(2)配置环境变量

1
2
3
4
5
6
# java环境
export JAVA_HOME=/usr/local/java/graalvm-ce-java17-22.1.0
export PATH=$PATH:$JAVA_HOME/bin
# maven环境
export MAVEN_HOME=/opt/soft/jenkins/maven_home
export PATH=$PATH:$MAVEN_HOME/bin

(3)安装 native-image
下载 native-image-installable-svm-java17-linux-amd64-22.1.0.jar ,上传到服务器,然后运行 gu 进行离线安装,也可以直接在线安装

1
2
3
4
5
6
7
8
# 离线安装
gu install -L native-image-installable-svm-java17-linux-amd64-22.1.0.jar

# 在线安装
gu install native-image

# 查看安装
gu list
参考文章:
【1】.Linux环境下GraalVM native-image将jar包编译为二进制 这里下载的是 graalvm-java8
【2】.解决Mac和Linux系统下Graalvm执行gu命令无效的问题 Windows系统下安装完Graalvm,由于其home/bin文件夹下面自带一个gu的cmd文件,该文件和java在一个目录下,可以直接通过cmd执行gu操作。但是Mac和Linux版本下,该安装包里面的gu是个空文件,默认无法执行任何操作。
【3】.GraalVM入门教程 gu 是 GraalVM 的组件安装器 (GraalVM Updater),你可以使用 gu 来安装、列出和卸载 GraalVM 中的各种组件。GraalVM是一个高性能、云原生、支持多种语言的虚拟机。GraalVM 提供了一个名为 “Native Image” 的工具,它能够将 Java 应用程序预编译成本机可执行文件。这种方法的优点是启动速度快,内存占用少,因为程序运行时不需要 JVM 和类加载。然而这种方式也存在一些弊端,如预编译的 GraalVM Native Image 相比于在 HotSpot JVM 上运行的相同程序,它没有一个先进的即时编译器 (JIT) ,因此就不能在运行时分析和优化代码,无法利用这些运行时优化,因此在性能表现上可能会有所降低。
【4】。GraalVM编译SpringBoot程序 上面两步全部运行成功之后,我们随意选择一个 Spring Boot 项目(必须是 SpringBoot 3.0 版本以上 + JDK17),比如我这里新建了一个 hello_graalvm 项目。进入项目主目录,命令行执行 mvn -Pnative native:compile ,等待 5~10 分钟,程序会自动在 /target 目录下生成一个本机可直接执行的文件,直接就能运行.
【5】.SpringNative GraalVM 打包 SpringBoot 为 Linux 的 单文件应用程序 执行命令 mvn clean package -DskipTests -Pnative 构建,构建速度较慢(取决于你服务器的性能),等构建完成后,在项目的 target 目录中就可以看到生成的单二进制文件了。

3.编译

编译有两种方式,一种就是使用 native-image 命令,将打包好的 jar 进行编译。

3.1.native-image

1
2
3
4
5
# 直接编译jar包
native-image -jar [jar包全路径] [编译后的文件名称]

# 必要时增加可执行权限
chmod +x demo && ./demo

3.2.mvn

(1) 引入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 <dependencies>
<dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
<version>${graalvm.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>native-image-maven-plugin</artifactId>
<version>${graalvm.version}</version>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<skip>false</skip>
<imageName>main</imageName>
<mainClass>org.example.Main</mainClass>
<buildArgs>
--no-fallback
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>

(2) 执行打包

1
2
3
4
# 进入项目根目录
cd test
# 执行编译
mvn -Pnative native:compile

4.window打包

参考文章:
【1】.手把手将你的Java maven项目通过GraalVM打包成windows可执行程序 1.安装Visual studio。2.配置cl.exe到系统的环境变量。错误:native-image - fatal error C1034: stdio.h: 不包括路径集;Default native-compiler executable ‘cl.exe’ not found via environment variable PATH;native-image 抛错fatal error 1083;Default native-compiler executable ‘cl.exe’ not found via environment variable PATH。
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。