王富贵

Stay hungry,Stay foolish

若你自认理性且正确,那更应该心平气和,言之有据地与人交流,即使不能立刻说服对方,但也至少埋下了一颗种子,冷嘲热讽或居高临下的态度,总会加大人与人之间的隔阂,最终只是在自己的小圈子中制造回声。愿我们最终都能成为乐观且包容的人,愿意耐心听取他人的苦衷和心声。
  menu
69 文章
0 浏览
0 当前访客
ღゝ◡╹)ノ❤️

spring-native

1、SpringNative

springboot3于2022年11月25日发布,强制要求jdk17,并拥有很多新特性。其中最重要的就是spring-native。

spring-native实际上是结合Oracle公司的 graalvm ,将java程序编译成二进制机器码,进行运行。

我们知道java是一门半编译半解释的语言

  • 编译:javac编译的时候会将部分直接调用c++的代码(native包调用),编译成jit代码缓存(jvm的元空间内)进行调用,而代码缓存是直接被编译成二进制机器码的。
  • 解释:结合了java虚拟机,将class文件放入java虚拟机进行解释运行。

java热门的原因是由java虚拟机赋予的:跨平台性,运行时创建对象(反射)。而在云原生遍地开花的时代,跨平台性已经被类似docker这种容器化技术所取代。而在云环境下,为了跑java应用还需要在虚拟容器中安装java运行环境,非常的麻烦。因此,将java编译成为二进制机器码,直接调用指令集成为我们不可不重视的功能。

表现在操作系统中就是,比如在windows下,编译后会直接打包成一个 exe 文件,我们直接双击运行就可以了。那么发给其他任何一个没有安装java环境(jdk)的人,都可以直接运行起来。

我们来对比一下新 graalvmhotspot的区别:

名称graalvmhotspot
原理编译成二进制机器码半解释半编译
环境不需要,直接操作系统下运行需要安装java(jdk)环境
运行内存占用非常小(70mb)比较大(300mb,要运行jvm)
启动速度微秒级(0.03ms)秒级(5600ms)
编译速度非常慢(300s)非常快(12s)

遗留问题

前面我们提到了AOT编译的好处,实际上jvm另外一个优点就是动态字节码。Java 过去之所以没有全面编译,并非占用内存增加和启动时间变慢,GraalVM Native Image 也需要编程很长时间,消耗很大的内存。实际上,GraalVM 是无法解决这个问题的,尤其是 JVM 字节码动态性,比如 CGLIB 动态生成或者 Java 反射的不确定性。其实,对于大多数业务代码,GraalVM AoT 编译器基本上可以完成静态化,主要是在框架代码上,有些麻烦,比如 Spring Stack,所以 Spring Native 做了大量的辅助工作,也帮助 GraalVM 提升稳定性,然而部分代码还需要自行声明。

参考

CSDN-SpringNative GraalVM 打包 SpringBoot 为 Windows 的 exe 应用程序

CSDN-Default native-compiler executable ‘cl.exe‘ not found via environment variable PATH

bilibili-【Java前沿】Spring6为什么强制要求JDK17?AOT到底是什么!技术专家必看!-极海Channel

1.1、使用graalvm

想要体验graalvm,我们只需要安装对应环境即可。我们知道graalvm会把java编译成为操作系统认知可运行的二进制文件,因此对应的编译工具是需要的。苹果和linux自带编译工具,因此不需要转其他东西,windows需要安装visualstudio来确保能编译成对应的可执行文件。

使用graalvm步骤如下:

  1. 安装graalvm ,配置环境变量, graalvm 目录和 graalvm/bin 目录。
  2. 安装对应操作系统内核的编译环境(可选,windows需要安装visualstudio)
  3. 使用编译环境编译java的class文件,也就是java编译后文件

1.2、win使用graalvm

我们尝试在windows下使用graalvm编译java程序。

1.3.1、安装GraalVM

GraalVM自带jdk,因此安装后就不需要额外安装jdk。由于springboot强制要求jdk17,因此GraalVM也建议安装代jdk17或以上的。

GraalVM22.3.0安装地址

1

安装完成之后解压,放在你配环境的位置。

然后配置环境变量,请注意,环境变量需要将GraalVM目录以及GraalVM目录下的bean目录放在path中。我们采用 JAVA_HOME 的方法。

2

path变量

3

当然,我们可以测试一下是否成功,打开cmd,输入两个命令

# 查看jdk版本
java -version

# gu命令
gu

4

gu命令是GraalVM内置的命令工具,如果你输入之后未找到命令,那就是GraalVM安装目录下的bin目录没有添加进环境变量的path中

1.3.2、安装VisualStudio

前面我们有提到过,windows并不自带内核可执行文件编译环境,因此需要安装,windows编译环境就是VisualStudio内的c++环境。

VisualStudio官网

VisualStudio历史版本

我们运行下载下来的 VisualStudioSetup ,必要的安装一下2个程序

1、 MSVC v143 - VS 2022 c++ x64/x86生成工具
# 根据你的jdk版本来选,jdk11需要MSVC v140 2015、jdk15需要MSVC v141 2017、jdk17需要MSVC v142 2019、jdk21需要MSVC v143 2022。当然他们向下兼容,如果你运行中出现了问题,尝试更换对应的版本。

2、Windows 11 SDK
# 根据你的windows版本选择,如果说windows10就选择win10

5

此外,我们需要重启电脑,假如你能搜索到并可以打开一个叫 x64 Native Tools Command Prompt for VS 2022的运行窗口,那么就安装成功了。

一定是x64的,如果是x86的后续会编译失败

记住这个窗口,非常重要,编译都需要在这个窗口中进行

6

在后需编译中可能出现报错:Default native-compiler executable ‘cl.exe‘ not found via environment variable PATH

因此,我们强烈建议你把 cl.exe 的路径添加在path中,例路径如下: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.16.27023\bin\HostX64\x64

路径可能会出现改动,如果不在 Program Files (x86) 路径下就是在 Program Files 下,也有其他路径可能出现问题请你多找一找。

我的路径就是: C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.34.31933\bin\Hostx64\x64

你要将这个路径添加进环境变量的 path

7

我们可以随意打开一个cmd,执行 cl.exe 命令,如果执行成功就说明环境变量添加成功

8

1.3.3、安装aot编译器native-image

我们之前已经将 GraalVM 添加入环境变量,使用 gu命令可以安装编译器native-image

  • 一定要打开之前的 x64 Native Tools Command Prompt for VS 2022 窗口,不能是普通cmd窗口,否则会执行失败
  • 执行 gu install native-image 命令

9

注意:

  1. 一定是截图窗口
  2. 一定是x64版本
  3. gu命令找不到的原因是graalvm目录下的bin目录没有配置环境变量

1.3.4、使用graalvm编译普通java程序

我们已经安装完了必要环境,具体步骤如下:

  1. 打开之前的 x64 Native Tools Command Prompt for VS 2022 窗口
  2. 切换到java程序所在的目录
  3. 将java程序使用 javac命令编译成class文件
  4. 使用native-image编译javac编译过的文件

1、我们编写一个普通的java程序

public class Hello {
    public static void main(String[] args) {
        System.out.println("hello graalVM");
        System.out.println("hello spring native");
    }
}

2、打开之前的 x64 Native Tools Command Prompt for VS 2022 窗口,切换java程序所在的目录,并执行 javac 命令将java文件编译

11

编译过后会生成一个 .class 文件

12

3、使用native-image编译编译过的文件,我的命令如下:native-image Hello

13

4.编译过后我们会获得一个可以直接执行的文件,在windows中就是 .exe 文件。我们可以直接运行起来

14

1.3.5、步骤总结

我们回顾一下使用的步骤

  1. 将java源文件使用 javac 编译成 class文件
  2. class文件 再编译成能够直接运行在操作系统上的二进制机器码,也就是当前操作系统内核直接运行的指令集
  3. windows下会直接编译成 exe 文件直接运行即可

需要注意的是,比较麻烦的是在编译的过程需要安装运行环境,而在 windows 中就是 c++ 环境 vs 了。

1.3、springNative使用

demo源码仓库地址spring-native-demo

spring-native在springboot3.0版本发布之后,也随之加入进来。前面我们有了解到,GraalVM本身就是吧javac编译的源文件直接打包编译成操作系统可以直接运行的文件,因此,springboot同样是编译之后再用GraalVM编译一遍即可。这个功能被集成到了maven的插件 native-maven-plugin 上。

我们可以大致了解以下步骤:

  1. 加入maven的插件 native-maven-plugin
  2. 使用windows的c++开发环境进行编译,也就是 x64 Native Tools Command Prompt for VS 2022 窗口

1.3.1、springboot3.0体验

注意:springboot3.0要求jdk不低于jdk17

1、首先我们需要快速创建一个springboot3.0版本的项目

15

2、添加spring-native插件,刷新maven之后就能看见插件

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

springboot3.0配置文件中已经添加了插件依赖,因此我们只要声明就行了,不需要指定版本。

插件的作用就是编译java并且使用操作系统的可执行内核程序进行编译。

16

3、使用 x64 Native Tools Command Prompt for VS 2022 窗口进行编译

在mac或者linux中是可以直接使用插件的 compile 功能进行编译,但是windows不行,必须使用这个窗口。需要跳转到项目目录中,进行maven指令编译。

我们需要先切换到项目目录下,windows下使用: cd /d [目标目录]

调用插件 native:compile 的指令为:mvn -Pnative native:compile

17

编译完成之后,会在 target 目录下生成一个 项目名.exe 文件,我们可以直接运行看效果


标题:spring-native
作者:1938857445
地址:https://www.lmlx66.top/articles/2022/11/28/1669620060095.html