在spring boot3中使用native image

news2024/7/6 18:41:36

文章目录

  • 简介
  • 安装GraalVM
    • 添加Native Image支持
  • 构建spring boot3应用
  • 总结

简介

在之前spring boot3文章中我们介绍了,spring boot3的一个重要特性就是支持把spring boot3的应用编译成为GraalVM的Native Image。

今天我们用具体的例子来给大家演示一下如何正确的将spring boot3的应用编译成为native image。

安装GraalVM

如果要把spring boot3的app编译成为native应用,需要GraalVM的支持。

什么是GraalVM呢?

从名字就可以看出来GraalVM是一个虚拟机,它的主要目标就是提升java应用程序的性能,并且消耗更少的资源。

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

所以,为什么要用GraalVM呢?一个字:快。

安装GraalVM也比较简单,我们进入它的官方下载页面下载对应的版本即可:https://www.oracle.com/downloads/graalvm-downloads.html。

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

要注意的是spring boot3需要GraalVM 22.3以上的版本支持,大家可不要下载错了。

下载完成之后,我们可以像正常安装JDK一样来安装GraalVM,这里以mac为例,假如我们安装的目录是/Library/Java/JavaVirtualMachines/graalvm-ee-java17-22.3.0,那么我们需要配置对应的JAVA_HOME和PATH环境变量如下:

 export PATH=/Library/Java/JavaVirtualMachines/graalvm-ee-java17-22.3.0/Contents/Home/bin:$PATH

 export JAVA_HOME=/Library/Java/JavaVirtualMachines/graalvm-ee-java17-22.3.0/Contents/Home

PATH中有一个非常重要的命令叫做gu,如果不添加PATH,那么在使用中就可能遇到下面的异常:

'gu' tool wasn't found. This probably means that JDK at isn't a GraalVM distribution.

安装完毕之后可以通过下面的命令来进行验证:

java -version
java version "17.0.5" 2022-10-18 LTS
Java(TM) SE Runtime Environment GraalVM EE 22.3.0 (build 17.0.5+9-LTS-jvmci-22.3-b07)
Java HotSpot(TM) 64-Bit Server VM GraalVM EE 22.3.0 (build 17.0.5+9-LTS-jvmci-22.3-b07, mixed mode, sharing)

如果是在mac环境下,还需要执行下面的命令来解除对graalvm的隔离限制:

 sudo xattr -r -d com.apple.quarantine /path/to/graalvm

否则在使用中就会遇到下面的问题:

添加Native Image支持

我们安装GraalVM的目的就是使用它的native Image特性。native image是一个单独的jar包,我们可以执行下面的命令来进行安装:

gu install native-image

其中gu就是/Library/Java/JavaVirtualMachines/graalvm-ee-java17-22.3.0/Contents/Home/bin中的命令。

下载的过程中还需要输入一个有效的邮件,并进行邮箱校验。然后一路ENTER就可以了。

当然,你还可以把Oracle GraalVM Enterprise Edition Native Image下载到本地,然后使用gu install -L来进行本地安装。

好了,到目前为止,一切准备妥当,我们接下来看看如何把spring boot3的应用打包成为native image吧。

构建spring boot3应用

这里我们使用的是maven,所以需要添加下面的spring boot3的依赖:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.1</version>
        <relativePath/> 
    </parent>

因为要构建native image,所以我们还需要用到下面的一个native-maven-plugin插件:

            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
            </plugin>

这里我们只创建了一个非常简单的main方法:

@SpringBootApplication
public class NativeImageApplication {

    public static void main(String[] args) {
        SpringApplication.run(NativeImageApplication.class, args);
    }

}

然后,我们尝试运行 mvn native:build来构建spring boot3应用程序。

记得在build之前一定先要编译好项目。

很可惜,你会发现下面的异常:

[INFO] --- native-maven-plugin:0.9.19:build (default-cli) @ native-image ---
[WARNING] 'native:build' goal is deprecated. Use 'native:compile-no-fork' instead.
[INFO] Found GraalVM installation from JAVA_HOME variable.
...
Error: Please specify class (or <module>/<mainclass>) containing the main entry point method. (see --help)

从上面的异常我们发现了两个问题,第一个问题是一个警告,它推荐我们使用native:compile-no-fork。

第二个问题是说找不到mainclass,根据异常信息,我们在pom的plugin中添加下面的配置信息,如下所示:

<plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
                <configuration>
                    <!-- imageName用于设置生成的二进制文件名称 -->
                    <imageName>${project.artifactId}</imageName>
                    <!-- mainClass用于指定main方法类路径 -->
                    <mainClass>com.flydean.nativeimage.NativeImageApplication</mainClass>
                    <buildArgs>
                        --no-fallback
                    </buildArgs>
                </configuration>
                <executions>
                    <execution>
                        <id>build-native</id>
                        <goals>
                            <goal>compile-no-fork</goal>
                        </goals>
                        <phase>package</phase>
                    </execution>
                </executions>
            </plugin>

然后重新运行mvn native:compile-no-fork:

GraalVM Native Image: Generating 'native-image' (executable)...
========================================================================================================================
[1/7] Initializing...                                                                                    (4.3s @ 0.25GB)
 Version info: 'GraalVM 22.3.0 Java 17 EE'
 Java version info: '17.0.5+9-LTS-jvmci-22.3-b07'
 C compiler: cc (apple, arm64, 14.0.0)
 Garbage collector: Serial GC
 1 user-specific feature(s)
 - org.springframework.aot.nativex.feature.PreComputeFieldFeature
Field org.apache.commons.logging.LogAdapter#log4jSpiPresent set to true at build time
Field org.apache.commons.logging.LogAdapter#log4jSlf4jProviderPresent set to true at build time
Field org.apache.commons.logging.LogAdapter#slf4jSpiPresent set to true at build time
Field org.apache.commons.logging.LogAdapter#slf4jApiPresent set to true at build time
Field org.springframework.core.NativeDetector#imageCode set to true at build time
Field org.springframework.core.KotlinDetector#kotlinPresent set to false at build time
Field org.springframework.core.KotlinDetector#kotlinReflectPresent set to false at build time
Field org.springframework.format.support.DefaultFormattingConversionService#jsr354Present set to false at build time
Field org.springframework.cglib.core.AbstractClassGenerator#imageCode set to true at build time
[2/7] Performing analysis...  [**********]                                                              (24.8s @ 4.57GB)
  10,266 (89.50%) of 11,470 classes reachable
  16,675 (63.53%) of 26,248 fields reachable
  53,776 (60.71%) of 88,575 methods reachable
     469 classes,   140 fields, and 2,281 methods registered for reflection
      63 classes,    69 fields, and    55 methods registered for JNI access
       5 native libraries: -framework CoreServices, -framework Foundation, dl, pthread, z
[3/7] Building universe...                                                                               (5.0s @ 2.72GB)
[4/7] Parsing methods...      [**]                                                                       (4.4s @ 2.42GB)
[5/7] Inlining methods...     [***]                                                                      (1.3s @ 3.87GB)
[6/7] Compiling methods...    [********]                                                                (70.0s @ 1.04GB)
[7/7] Creating image...                                                                                  (4.7s @ 3.35GB)
  30.27MB (58.75%) for code area:    30,771 compilation units
  20.50MB (39.79%) for image heap:  305,579 objects and 93 resources
 769.52KB ( 1.46%) for other data
  51.52MB in total
------------------------------------------------------------------------------------------------------------------------
Top 10 packages in code area:                               Top 10 object types in image heap:
   2.02MB com.oracle.svm.core.code                             5.79MB byte[] for code metadata
   1.77MB sun.security.ssl                                     2.31MB byte[] for java.lang.String
   1.29MB java.util                                            2.09MB byte[] for general heap data
 929.52KB java.lang.invoke                                     2.07MB java.lang.String
 925.96KB com.sun.crypto.provider                              1.76MB java.lang.Class
 802.99KB java.lang                                          671.09KB byte[] for embedded resources
 633.35KB sun.nio.ch                                         567.26KB byte[] for reflection metadata
 625.89KB java.util.concurrent                               481.22KB com.oracle.svm.core.hub.DynamicHubCompanion
 601.86KB org.apache.tomcat.util.net                         450.06KB java.util.HashMap$Node
 594.48KB sun.security.x509                                  401.78KB java.util.concurrent.ConcurrentHashMap$Node
  20.02MB for 397 more packages                                3.40MB for 2297 more object types
------------------------------------------------------------------------------------------------------------------------
                        9.5s (7.9% of total time) in 50 GCs | Peak RSS: 3.75GB | CPU load: 4.39
------------------------------------------------------------------------------------------------------------------------
Produced artifacts:
 /Users/learn-springboot3/learn-springboot3/native-image/target/native-image (executable)
 /Users/learn-springboot3/learn-springboot3/native-image/target/native-image.build_artifacts.txt (txt)
========================================================================================================================
Finished generating 'native-image' in 2m 0s.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  02:01 min
[INFO] Finished at: 2023-01-05T20:43:39+08:00
[INFO] ------------------------------------------------------------------------

经过漫长的等待,我们终于build完成了。

因为我们的artifactId叫做native-image,所以最终在target目录下面生成了一个叫做native-image的可执行文件:

.
├── classes
│   ├── application.properties
│   └── com
│       └── flydean
│           └── nativeimage
│               └── NativeImageApplication.class
├── generated-sources
│   └── annotations
├── generated-test-sources
│   └── test-annotations
├── maven-archiver
│   └── pom.properties
├── maven-status
│   └── maven-compiler-plugin
│       ├── compile
│       │   └── default-compile
│       │       ├── createdFiles.lst
│       │       └── inputFiles.lst
│       └── testCompile
│           └── default-testCompile
│               ├── createdFiles.lst
│               └── inputFiles.lst
├── native-image
├── native-image-0.0.1-SNAPSHOT.jar
├── native-image-0.0.1-SNAPSHOT.jar.original
├── native-image.build_artifacts.txt
├── surefire-reports
│   ├── TEST-com.flydean.nativeimage.NativeImageApplicationTests.xml
│   └── com.flydean.nativeimage.NativeImageApplicationTests.txt
└── test-classes
    └── com
        └── flydean
            └── nativeimage
                └── NativeImageApplicationTests.class

20 directories, 14 files

如果你这时候运行target/native-image,那么很可能得到下面的异常:

[main] DEBUG org.springframework.context.aot.AotApplicationContextInitializer - Initializing ApplicationContext with AOT
[main] ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.IllegalArgumentException: Could not find class [com.flydean.nativeimage.NativeImageApplication__ApplicationContextInitializer]
        at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:333)

这是因为我们缺少一些spring boot的AOT元文件信息,正确的做法是使用下面的命令:

mvn clean package -Pnative

它实际上执行的是下面的几个命令:

mvn spring-boot:process-aot
mvn spring-boot:process-test-aot
mvn spring-boot:build-image

最终我们得到编译好的native-image信息,运行得到下面的结果:

2023-01-05T17:07:11.692+08:00  INFO 69299 --- [           main] c.f.nativeimage.NativeImageApplication   : Starting AOT-processed NativeImageApplication using Java 17.0.5 with PID 69299 (/Users/wayne/data/git/ddean2009/learn-springboot3/learn-springboot3/native-image/target/native-image started by wayne in /Users/wayne/data/git/ddean2009/learn-springboot3/learn-springboot3/native-image)
2023-01-05T17:07:11.693+08:00  INFO 69299 --- [           main] c.f.nativeimage.NativeImageApplication   : No active profile set, falling back to 1 default profile: "default"
2023-01-05T17:07:11.709+08:00  INFO 69299 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2023-01-05T17:07:11.710+08:00  INFO 69299 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-01-05T17:07:11.710+08:00  INFO 69299 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.4]
2023-01-05T17:07:11.717+08:00  INFO 69299 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-01-05T17:07:11.717+08:00  INFO 69299 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 24 ms
2023-01-05T17:07:11.729+08:00  INFO 69299 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-01-05T17:07:11.729+08:00  INFO 69299 --- [           main] c.f.nativeimage.NativeImageApplication   : Started NativeImageApplication in 0.053 seconds (process running for 0.072)

总结

从运行情况来看,native-image的启动速度非常快,应该可以提升不少的性能。

感兴趣的小伙伴赶紧用起来吧。

本文的例子https://github.com/ddean2009/learn-springboot3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/185975.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nacos 删除过期实例源码分析

nacos 删除过期实例也是注册中心的一个重要功能&#xff0c;今天我们从入口到结束分析一下&#xff0c;首先确定删除的入口在服务端注册接口的源码里&#xff0c;此处可以参考&#xff1a;参考注册源码 一、注册入口 1、创建空服务 public void registerInstance(String name…

行测笔记(主要知识点)

文章目录&#xff1a; 一&#xff1a;言语理解 1.技巧关系 2.逻辑填空 二&#xff1a;判断推理 1.图形推理 2.定义判断 3.类比推理 4.逻辑判断 三&#xff1a;资料分析 1.增长率 2.增长量 3.比重 4.平均数 5.倍数与比值 三&#xff1a;数量关系 1.解题…

Nozomi 交付业界第一个物联网端点安全传感器

运营技术 (OT) 和物联网 (IoT) 安全提供商 Nozomi Networks 推出了业界首款 OT 和物联网端点安全传感器 Nozomi Arc&#xff0c;旨在以指数方式加快实现完全运营弹性的时间。 Nozomi Arc 旨在自动部署在组织需要可见性的任何地方的大量站点和设备上&#xff0c;添加了关于关键…

六个步骤教你用Xmind制作思维导图

XMind是国产优秀的思维导图软件&#xff0c;那么如何使用xmind制作思维导图呢&#xff1f;对于新手来说&#xff0c;首先就要正确安装Xmind&#xff1b;其次&#xff0c;就是要搞清楚使用XMind画思维导图的步骤和方法&#xff0c;当然在学习使用xmind画思维导图的过程中也可以学…

Redis 面试题总结

Redis是什么&#xff1f; Redis 是一个 key-value 存储系统&#xff0c;它支持存储的 value 类型相对更多&#xff0c;包括 string、list、set、zset&#xff08;sorted set --有序集合&#xff09;和 hash。这些数据结构都支持 push/pop、add/remove 及取交集并集和差集及更丰…

面试题 : Spring循环依赖问题及其解决方案

一级缓存,存在循环依赖问题 一级缓存的作用 一级缓存就是singletonObjects(单例池) : 作用就是保证单例,里面放的是成品对象循环依赖问题 假设有两个类A, B ,然后A依赖B, B依赖A此时在spring 容器中一级缓存的工作流程是&#xff1a; (1)、首先在单例池中找,一开始是没有的…

2023年二月份图形化一级打卡试题

活动时间 从2023年 2月1日至1月21日&#xff0c;每天一道编程题。 本次打卡的规则如下&#xff1a; &#xff08;1&#xff09;小朋友每天利用10~15分钟做一道编程题&#xff0c;遇到问题就来群内讨论&#xff0c;我来给大家答疑。 &#xff08;2&#xff09;小朋友做完题目后&…

SharedWorker 让你多个页面相互通信

SharedWorker 是一个新的Web Worker API&#xff0c;它允许你在多个页面之间共享一个Worker。 SharedWorker 代表一种特定类型的Worker&#xff0c;可以在多个浏览器上下文中运行&#xff0c;比如多个页面或者多个iframe。 什么是 SharedWorker 根据前几篇的了解&#xff0c…

i.MX8MM开发板音视频开发-音频编码

我们举个例子&#xff0c;以 CD 音质来说&#xff0c;量化格式是 2 字节&#xff0c;采样率是 44100&#xff0c;声道数是 2&#xff0c;这些信息就描述 了 CD 的音质。对于声音信息&#xff0c;我们还可以用数据比特率来描述音频数据单位时间内的容量大小。那么 CD 的 数 据 采…

【Java AWT 图形界面编程】Frame 窗口中进行自定义布局 ( AWT 中常用的布局容器 )

文章目录一、Frame 窗口中进行自定义布局二、AWT 中常用的布局容器一、Frame 窗口中进行自定义布局 在 【Java AWT 图形界面编程】LayoutManager 布局管理器总结 ( FlowLayout 布局 | BorderLayout 布局 | BoxLayout 布局 ) 介绍了常用的布局 ; 使用布局的好处是 布局内的子组…

【服务器数据恢复】ZFS文件系统下RAIDZ的数据恢复案例

服务器数据恢复环境&#xff1a; ORACLE Sun ZFS Storage&#xff1b; 32块磁盘分为4组&#xff0c;每组8块硬盘&#xff0c;热备盘全部启用。 ZFS文件系统&#xff0c;Windows操作系统。 服务器故障&分析&#xff1a; 设备在正常工作时候突然崩溃&#xff0c;经过检查排除…

机器学习笔记之深度玻尔兹曼机(三)预训练思路整理

机器学习笔记之深度玻尔兹曼机——预训练思路整理引言回顾&#xff1a;受限玻尔兹曼机的叠加逻辑回顾&#xff1a;受限玻尔兹曼机叠加过程中的计算方式关于计算过程的优化引言 上一节介绍了受限玻尔兹曼机叠加的逻辑&#xff0c;以及叠加过程中出现的Double Counting\text{Dou…

理解 TypeScript 背后的结构化类型系统

前言 你能说清楚类型、类型系统、类型检查这三个的区别吗&#xff1f;在理解TypeScript的结构化类型系统之前&#xff0c;我们首先要搞清楚这三个概念和它们之间的关系 类型&#xff1a;即对变量的访问限制与赋值限制。如 TypeScript 中的原始类型、对象类型、函数类型和字面…

python代码实现批量yunfile文件下载

建议下载文件大小不要超过1M吧,超过的话,把等待下载时间加大点 —>说明: 使用python2.7+selenium+chrome v49+百度ocr识别,基本上pip install 相关的程序,源码就可以直接运行了,exe文件也编译了,去别的电脑运行感觉有各种问题,大家自己用源码跑吧,最新chrome版本的…

如何实现报表集成?(一)

报表需求在每个企业都是“刚需”&#xff0c;而报表的应用又是其中的关键之一&#xff0c;并不是说报表开发出来就万事大吉了&#xff0c;怎么用、怎么用得好&#xff0c;也是用户非常关注的。在这个话题中&#xff0c;报表的集成是个绕不过去的坎&#xff0c;如何通过集成&…

机器学习之参数学习

下述内容为课程小结 定义 参数估计的方法包括经验风险最小化、结构风险最小化、最大似然估计、最大后验估计。 参数估计用于学习模型参数&#xff0c;以达到最优的目的&#xff0c;如线性回归的模型参数 经验风险最小化 对于输入的待处理数据格式为(x&#xff0c;y){(x&…

Plant Simulation热力图工具V2.1全新发布

在做AGV路径规划或人员路径规划时&#xff0c;如果配套热力图&#xff0c;是可以非常方便的分析出相应位置的热点情况&#xff0c;决策人员可以更加方便的确定方案修改思路&#xff0c;比如下图可以非常清晰地看到AGV的停顿位置和路口的使用情况。较早之前&#xff0c;波哥开发…

Vue3+Vite+Element-Plus实现CRUD常见表单项目

效果有 查询&#xff0c;增加&#xff0c;表格&#xff0c;删除&#xff0c;编辑 其实CRUD&#xff0c;就是一个管理项目最常见的功能 C增加 (Create) R读取 (Read) U更新 (Update) D删除 (Delete) 一、创建项目 vue3用vite创建项目 1 对应路径cmd 输入 npm create vitelates…

C 语言零基础入门教程(十八)

C 输入 & 输出 当我们提到输入时&#xff0c;这意味着要向程序填充一些数据。输入可以是以文件的形式或从命令行中进行。C 语言提供了一系列内置的函数来读取给定的输入&#xff0c;并根据需要填充到程序中。 当我们提到输出时&#xff0c;这意味着要在屏幕上、打印机上或…

SSM框架整合(Spring+SpringMVC+MyBatis)

一、创建MAVEN工程 二、导入pom依赖 <dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version></dependency><!-- https://mvnrepository.com/artifact/commons-logging/comm…