SpringBoot: 使用GraalVM编译native应用

曾今Go语言里让我最艳羡的两个特性,一个是Goroutine,一个是native编译。 Java 21的虚线程实现了类似Goroutine的能力。Spring Boot 3.x开始提供了GraalVM的支持,现在Spring Boot也能打包成native文件了。

这一篇文章的目标是用一个案例讲解如何将Spring Boot应用打包成native文件。整个过程主要是4步:

  1. 环境准备,讲解怎么安装GraalVM,安装本地编译器(gcc,cl)
  2. 测试工程,创建一个极简的Spring Boot应用,只有个Controller
  3. 编译打包,使用GraalVM、Maven将Spring Boot应用构建成可执行文件
  4. 测试运行,执行生成的可执行文件,访问Controller看是否正常

1. 环境准备

1. 前置条件

GraalVM依赖一些本地工具才能完成工作,这些工具包括:

  • C的头文件
  • glibc-devel
  • zlib
  • gcc
  • libstdc++-static

不同的操作系统,采用的安装方式不同,在Linux下可以使用包管理工具安装,比如yum、apt等

Linux

yum install gcc glibc-devel zlib-devel
apt-get install build-essential libz-dev zlib1g-dev

Windows

Windows可以通过安装Visual Studio完成依赖包安装

  1. 安装Visual Studio Build Tools
  2. 安装Visual Studio
2. 安装GraalVM

从官网选择Java版本、平台来下载,下载的zip包解压即安装,接下来只要设置环境变量JAVA_HOME、PATH即可

  • 设置GRAALVM_HOME为解压文件夹的根目录
  • 设置PATH为解压文件夹下的bin
3. 验证安装

通过执行native-image --help,确认我们安装成功

4. 参考资料

关于GraalVM的安装过程,可以参考官方的Get Started文档: Getting Started with GraalVM

2. 测试工程

1. 创建工程

使用mvn archetype:generate根据archetype maven-archetype-quickstart生成一个最简单的Java项目。

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DgroupId=com.keyniu.dis -DartifactId=DiveInSpring -Dversion=0.1 -Dpackage=com.keyniu.dis -DinteractiveMode=false
2. 添加Spring Boot支持

修改pom.xml选择spring-boot-starter-parent作为parent,添加native-maven-plugin插件

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.keyniu.dis</groupId><artifactId>DiveInSpring</artifactId><version>0.1</version><name>DiveInSpring</name><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.0</version></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId></plugin></plugins></build></project>
3. 添加测试类

写一个最简单启动引导类,提供一个最简单的接口/hello,用于后续测试。

package com.keyniu.dis;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@SpringBootApplication
@RestController
public class DiveInMain {@GetMapping("/hello")public String hello(@RequestParam("name") String name) {return "hello," + name;}public static void main(String[] args) {SpringApplication.run(DiveInMain.class);}
}

3. 编译打包

1. 命令行窗口

为了让GraalVM能引用到VisualStudio的编译工具,我选择在x64 Native Tools窗口中运行接下来的命令。

在执行命令之前,确保你的环境变量设置正确,有添加GraalVM相关的配置

set GRAALVM_HOME=D:\Programs\GraalVM
set PATH=D:\Programs\GraalVM\bin;%PATH%
2. 进行native编译

在工程的根目录下执行mvn -Pnative native:compile,进行编译,最后会生成一个exe到工程的target目录下,输入如下

D:\Workspace\DiveInSpring>mvn -Pnative native:compile
...
Produced artifacts:D:\Workspace\DiveInSpring\target\DiveInSpring.exe (executable)

4. 测试运行

只需要在命令行里输入DiveInSpring.exe执行,可以看到只需要0.063s就能完成启动,这个项目如果通过java -jar启动的话大概耗时0.97s,还是快了很多的。打包后的exe文件大小是80M。

通过curl命令验证,接口正常提供服务

5. 使用建议

可以看到整个构建过程已经相当的顺畅,从可执行文件的大小,启动时间,内存占用都于明显的提升,应该说Spring + GraalVM离成熟应用已经不远了。由于GraalVM使用了Closed World Optimization,实际上这个可执行程序还是有一些限制的,主要是:

  1. Class初始化,有些初始化会在build期间完成,可以参考GraalVM文档: Class Initialization in Native Image
  2. 反射和动态代理,需要的编译期间完成
  3. 不支持JNI,如果有本地方法调用需要根据GraalVM提供的接口定制实现
  4. 执行时无法访问字节码,正常的debug、监控等用JVM TI实现的功能都不再可用

在SpringBoot中, 像profiles、 条件配置、 @Enable*等功能会受到影响,而其实这些特性正在被广泛使用,这些限制在完全解决之前实际使用还是有障碍的。关于可以执行文件的DEBUG、监控在GraalVM官网都已经有对应的文档,但是将它和公司内部的监控报警做集成还有一段路要走,已经看到黎明的曙光了。

A. 参考资料

  1. GraalVM构建Swing应用
  2. 使用GDB Debug由GraalVM构建的程序,Debug Native Executables with GDB
  3. 让可执行文件支持JFR,Build and Run Native Executables with JFR
  4. 手动创建Spring Boot工程

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

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

相关文章

pidstat -d 1分析磁盘吞吐量

iostat -dx 1 查看磁盘IO吞吐量 pidstat -d 1看是哪个进程写的

水电站大坝安全监测工作详解

水电站大坝安全监测是确保大坝结构安全和操作安全的关键组成部分。本文将详细解释水电站大坝安全监测的9项主要工作内容&#xff0c;帮助理解其重要性和执行过程。 1) 现场监测 现场监测是水电站大坝安全监测的首要步骤。监测人员需要定期对大坝的物理结构进行检查&#xff0c;…

论文AI率不达标?AI工具助你一臂之力

告诉大家一个非常残忍的答案&#xff0c;以后所有论文都会被查ai率的。 学术界不仅关注传统的抄袭问题&#xff0c;还增加了一项名为“AIGC检测”的指标。例如知网、维普等平台都能检测论文AI率。 用GPT写论文虽然重复率基本不用担心&#xff0c;但是AI率基本都较高&#xff…

在 Qt Creator 上创建 ROS 项目并新建/导入 ROS 包

0、引言 ⚠️ 在开始之前&#xff0c;您需要确保您已经为 Qt 配置好了 ROS 开发环境了。如果您还没有配置好&#xff0c;可以参考这篇文章 本文将着手探讨如何在 Qt Creator 上编辑 ROS 项目&#xff08;工作空间&#xff09;。 1、本教程使用到的相关软件或产品 Ubuntu 20.0…

OpenCV学习(4.2) 图像的几何变换

1.目标 学习将不同的几何变换应用到图像上&#xff0c;如平移、旋转、仿射变换等。你会看到这些函数: cv.getPerspectiveTransform 2.缩放 缩放是调整图片的大小。 OpenCV 使用 cv.resize() 函数进行调整。可以手动指定图像的大小&#xff0c;也可以指定比例因子。可以使用不…

【Vue】小黑记事本

文章目录 一、需求说明二、思路分析三、代码实现 一、需求说明 拆分基础组件渲染待办任务添加任务删除任务底部合计 和 清空功能持久化存储 二、思路分析 拆分基础组件 咱们可以把小黑记事本原有的结构拆成三部分内容&#xff1a;头部&#xff08;TodoHeader&#xff09;、列…

基于semantic_kernel的ChatMD系统

问答系统需求文档 一、项目概述 本项目旨在开发一个能够上传 MD 文件&#xff0c;并基于 MD内容进行问答互动的系统。用户可以上传 MD文件&#xff0c;系统将解析 MD内容&#xff0c;并允许用户通过对话框进行问答互动&#xff0c;获取有关 MD文件内容的信息。 二、功能需求…

保研面试408复习 8——计算机网络(浏览器http)、离散数学(平面图)、操作系统、数据结构

文章目录 一、计算机网络1、从在浏览器输入网址到页面显示的过程1. 输入网址2. DNS 解析3. 建立TCP连接4. 发送HTTP请求5. 服务器处理请求并响应6. 浏览器处理响应7. 页面渲染 二、离散数学一、平面图1、平面图性质2、Kuratowski定理 三、操作系统四、数据结构 一、计算机网络 …

IDCF五周年专场—【研发效能·创享大会】圆满落幕!

2024 年5 月25 日&#xff0c;【研发效能创享大会】—IDCF五周年专场在北京希尔顿欢朋酒店&#xff08;大红门&#xff09;成功举办&#xff01;本次大会旨在为社区成员提供一个学习与交流的平台&#xff0c;分享技术经验&#xff0c;交流行业见解&#xff0c;促进技术合作与创…

【Java基础】线程的五大状态

新建状态 使用 new 关键字和 Thread 类或其子类建立一个线程对象后&#xff0c;该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。 就绪状态 当线程对象调用了start()方法之后&#xff0c;该线程就进入就绪状态。就绪状态的线程处于就绪队列中&#xff…

景深技术在AI绘画中的魔法:为数字艺术注入新维度

引言&#xff1a; 在人工智能&#xff08;AI&#xff09;的浪潮中&#xff0c;绘画艺术领域迎来了革命性的变革。AI绘画不仅改变了创作过程&#xff0c;还为艺术家和设计师提供了前所未有的工具。其中&#xff0c;景深技术作为一种重要的视觉处理手段&#xff0c;在AI绘画中的应…

告别繁琐,Xinstall一键解决App代理结算难题!

在移动互联网的浪潮中&#xff0c;App的推广和运营成为了众多企业和开发者关注的焦点。然而&#xff0c;随着App市场的日益竞争&#xff0c;代理结算的复杂性和繁琐性成为了许多推广者头疼的问题。为了解决这个问题&#xff0c;Xinstall凭借其专业的技术和丰富的服务经验&#…

Modebus通信协议 温控器示例

目录 1 指令解释 2 获取动态的CRC 3 crc在线验证 4 16进制正负温度互转 4.2 16进制转温度 4.2 温度转16进制 5 完整工具类 最近安卓工作接了很多硬件&#xff0c;其他的都是发个固定指令&#xff0c;比较有代表性就是温控器和打印机自定义内容所以这个记录接入示例&…

为什么没有输出九九乘法表?

下面的程序本来想输出九九乘法表到屏幕上&#xff0c;为什么没有输出呢&#xff1f;怎样修改&#xff1f; <!DOCTYPE html> <html> <head> <meta charset"utf-8" /> <title>我的HTML练习</title> …

新火种AI|倒反天罡!美国名校斯坦福AI团队抄袭中国大模型

作者&#xff1a;一号 编辑&#xff1a;美美 中国大模型被抄袭&#xff0c;怎么不算是某种层面上的国际认可呢&#xff1f; 5月29日&#xff0c;斯坦福大学的一个AI研究团队发布了一个名为「Llama3V」的模型&#xff0c;号称只要 500 美元就能训练出一个 SOTA 多模态模型&am…

知识库系统:从认识到搭建

在这个信息过载的时代&#xff0c;企业越来越需要一个集中的知识库系统来促进员工协作和解决问题。本文跟着LookLook同学一起来探讨搭建高效知识库系统的所有注意事项和知识库系统的最佳推荐。 | 什么是知识库系统 知识库系统是一种软件或工具&#xff0c;旨在填补组织内的知识…

超越传统AI 新型多智能体系统MESA,探索效率大幅提升

探索多智能体强化学习的协同元探索 —— MESA 算法深度解读在多智能体强化学习&#xff08;MARL&#xff09;的征途中&#xff0c;如何高效探索以发现最优策略一直是研究者们面临的挑战。特别是在稀疏奖励的环境中&#xff0c;这一问题变得更加棘手。《MESA: Cooperative Meta-…

用扫描书籍的功能扫描文档是扫描件吗?

当使用扫描书籍的功能来扫描文档时&#xff0c;产生的结果通常被称为“扫描件”或“扫描图像”。这里的“扫描”一词指的是通过扫描仪或具有扫描功能的设备&#xff08;如一些高端打印机、多功能一体机等&#xff09;将纸质文档转换为数字图像的过程。 扫描件通常是高清晰度的…

关于phpstorm创建类和方法时带描述注释

展示效果&#xff1a; 1、使用phpstorm创建类文件时自带注释及注释编辑 步骤1&#xff1a; 步骤二&#xff1a; 内容&#xff1a; <?php /** * Desc: * author guowei * datetime $DATE $TIME */ #if (${NAMESPACE}) namespace ${NAMESPACE}; #end class ${NAM…

计算机网络 —— 数据链路层(以太网)

计算机网络 —— 数据链路层&#xff08;以太网&#xff09; 什么是以太网以太网传输介质和拓扑结构的发展传输介质的发展&#xff1a;拓扑结构的发展&#xff1a; 10BASE-T 以太网适配器和MAC地址适配器&#xff08;Adapter&#xff09;MAC地址适配器与MAC地址的关系 MAC帧以太…