
近几年“原生”一词一直泛滥在云计算、边缘计算等领域中,而原生宠幸的语言也一直都是Golang,Rust等脱离Sandbox运行的开发语言。Java得益于上世纪流行的一次编译,到处执行的理念,流行至今,但也因为这个原因,导致Java程序脱离不了JVM运行环境,使得不那么受原生程序的青睐。在云原生泛滥的今天,臃肿的JVM使Java应用程序对比其他语言显得无比的庞大,各路大神也想了很多方式让Java变的更“原生”。最近Spring推出了Spring Native概念,并参考了其他大牛的文章后,今天我们就一探如何让用Spring Boot编写原生应用。
Spring Native借助GraalVM native-image编译器来编译Spring应用,所以我们需要先来了解一下GraalVM。大部分脚本语言或者有动态特效的语言都需要一个语言虚拟机运行,比如CPython,Lua,Erlang,Java,Ruby,R,JS,PHP,Perl,APL等等,但是这些语言的虚拟机水平参差不齐,例如JVM的HotSpotVM、JS的V8都是“艺术”级别的,但CPython的VM就不忍直视。那能不能用一个“艺术”级别的虚拟机跑所有的语言呢?GraalVM就是这么一个高性能的救世主,它使用运行在JVM上的Truffle语言框架,将AST节点编译为机器代码,使用户只需要实现具体语言AST解释器,就能实现性能足够好的虚拟机,而实现这个编译器也是一个Java写的即时编译器Graal,GraalVM也因此得名。
也许有同学会问了怎么用Java语言编译Java代码呢,而且还是这么高性能?这我们就要说说JEP 243的JVMCI。众所周知,HotSpot JVM内置了两个C++写的即时编译器(JIT)C1和C2,一般频繁的代码先用C1编译,如果热点继续,那么会使用C2编译。JVMCI相当于把本该交给C2编译的代码交给高级JIT:Graal编译,说到底就是将一段byte[]在运行时换成另一段byte[]。
那像Go和C/C++这类语言是否也能运行在JVM上呢?答案是肯定的。解决方案是将C/C++这些语言用一些工具(如Clang)转换为LLVM IR,然后使用基于Truffle的AST解释LLVM IR即可。(但,我们为啥要这么做??)

到目前为止,几乎所有的语言都能在以JVM为基础,以Graal即时编译器为核心的虚拟机上运行起来了,但大家已经一定疑惑了,程序运行需要依赖JVM,而JVM必须提前安装JDK环境,而且自身启动慢,内存负载高,就不能把程序直接打包成平台相关可执行文件吗?答案是SubstrateVM,它借助Graal编译器,可以将Java程序AOT编译为可执行程序。所以万能的Graal编译器不仅能JIT,还能AOT。

好了,我们这些“CRUD仔”们了解这些基础魔法就足够了,至于SVM如何解决反射、GC等问题的高级魔法还是交给大牛们吧。现在进入我们的正题:用Spring Boot来编写一个原生应用。
制作过程

Step 1:安装GraalVM和依赖工具
因为大家都比较熟悉JDK安装过程,所以本过程带过了一些细节,不做重点讲解。首先我们需要安装GraalVM,笔者以自己的macOS系统为例,其他系统请参考官方安装文档。比较遗憾的是,GraalVM并没有提供针对M1优化的AArch64平台的包,我们只能使用AMD64平台,下载地址点击这里[1],我们使用Java 17版本的darwin压缩包,解压至:
/Library/Java/JavaVirtualMachines/
并且设置JAVA_HOME:
export GRAALVM17_HOME=$(/usr/libexec/java_home -v 17)
export JAVA_HOME=$GRAALVM

本文介绍了Spring Native,一种借助GraalVM native-image编译器将Spring Boot应用转化为原生应用的方法。通过GraalVM,Java应用程序可以摆脱JVM,实现更接近原生性能和更小的体积。文章详细讲述了安装GraalVM、建立Spring Boot应用、配置Maven以及编译原生应用的过程,并对比了原生应用与传统jar包在启动速度、内存占用和文件大小上的差异。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



