GraalVM简介

简介

GraalVM是一个高性能的JDK,它能加速Java应用的执行速度,同时为其他语言提供运行环境,如JavaScript、Python、Rust等等。官网

新的技术总是会给我们契机去了解这个领域内技术的发展,GraalVM能带领我们去走进虚拟机与编译器。

GraalVM的特点

借鉴

  • 加快Java应用的启动

    GraalVM能将Java应用的启动时间减少到1/50

  • 节省内存

    GraalVM能减少4/5的内存

  • 节省硬盘

    GraalVM能将docker镜像的大小降低70%

  • 多语言支持,统一语言工具链

    不仅可以运行Java,还可以运行js、ruby、python等语言,可以用统一的语言进行调试;

    Java代码可以无缝调用其他语言的功能和三方库

前3点的特性感觉就是为解决Java上云的,基本解决了Java上云占用资源过多的问题,这也是Spring Native的初衷吧

虚拟机的进化

参考Java代码的执行过程:

Java代码执行流程

对于CPython,R,Ruby,PHP乃至自己写的一门新的语言,回顾一下我们的一般做法:

  • 首先解析源代码到AST,然后写一个AST解释器执行代码

  • 当有些人用这个语言的时候,语言设计者可能继续迭代,实现一个虚拟机,包括GC,运行时等,代码执行仍然是AST解释器

  • 用的人多了,继续迭代,将AST转换为字节码,使用字节码解释器

  • 用的人特别多,性能也很关键,如果这个语言社区有足够资金和人力,那么可以写JIT编译器,提升GC性能等,大部分语言都到不了这一步。

借鉴

我不太看好其他语言运行于GraalVM之上,因为其他语言成熟的虚拟机如v8引擎本来就很优秀了,没必要往这个上搬,只能为一些不太优秀的提供一个路径,主要是服务Java语言,能用Java调用其他语言。

GraalVM的结构

v2-7205d1f7d9ff516da1ff8628dd655639_r

https://www.zhihu.com/question/28927570/answer/2058826630

JIT编译器

JIT编译器是JVM的一部分,负责把字节码编译成机器码然后执行。

具体到hotsport虚拟机,叫做c1、c2编译器

JVMCI

Java9之后提供的一个接口,全称是JVM Compiler interface,java虚拟机编译器接口,提供可以插拔的编译器接口。也就是说Java虚拟机提供了一个允许用户自定义JIT编译器的接口,可以用来替代C2. 这样就有了Graal JIT,上图中就是这个意思,用Graal JIT替换了C2 JIT的hotspot虚拟机。

Graal Compiler

跟用c++编写的c2编译器不一样,graal编译器是由java编写而成的。

graal既然能做到jit,同样也能实现aot,aot是什么?

jit是先通过javac将源码编译成字节码,然后再在运行时,由jvm里面的jit编译器,将字节码编译成机器码以执行的过程;

aot是在编译的时候,直接将源代码编译成机器码的过程;aot在编译的时候,直接将源代码编译成机器代码,然后将其打包成目标平台的格式,这个工具在graal中叫做native image。生成的机器码格式里面,没有完整的jvm,但是有一些用于支持其运行的组件,被称为substrate vm(基层虚拟机)。

aot_vs_jit-640x393

也正是这个原因,所以才有了之前提到的特点。

Truffle

动态脚本语言,如python、JavaScript等,本身就不需要编译,都是解释执行,这跟aot的过程是类似的,所以graalvm就做了一个转换接口,将这些脚本语言翻译成graal认识的格式,这就是Truffle干的事。

目前这一部分,只适用于比较简单的语言,如python、js等语言估计需要很多的工作。

另外:既然从java上这条路能走通,从其他语言JIT应该也能走通。

GraalVM的使用

参考

下载与安装

  1. 下载,官方地址,当前最新是:22.3.0

  2. 解压

  3. 修改环境变量

    # 修改/etc/profile
    export JAVA_HOME=/path/to/graalvm
    export PATH=/path/to/graalvm:$PATH
    
    # 生效
    source /etc/profile
    
  4. 确定是否成功

    java  -version
    

初步应用

  1. 利用gu下载native-image

    gu类似于pip、npm等工具

    sudo gu install native-image
    
  2. HelloWorld.java代码

    public class HelloWorld {
      public static void main(String[] args) {
        System.out.println("Hello, World!");
      }
    }
    
  3. 编译与打包

    javac HelloWorld.java
    native-image HelloWorld
    

    这个要注意$CLASSPATHexport CLASSPATH=.:${JAVA_HOME}/lib:${JAVA_HOME}/jre/lib,要有.,否则找不到类。

    执行完成之后,在目录下生成HelloWorld启动程序。

  4. 运行

    ./HelloWold
    

IDEA中使用

现在用的插件是native-maven-plugin,官方文档](https://graalvm.github.io/native-build-tools/latest/maven-plugin.html)

  • 创建Spring Initializr工程

  • 添加GraalVM NativeSupport

  • 增加native-maven-plugin插件

  • 添加测试代码

  • 使用插件打包mvn spring-boot:build-image

    经过几次尝试,一直显示启动不了,显示:Could not find class xxx_ApplicationContextInitializer,后来选择mvn的profile后,问题解决

    这里要注意mvn的profile要选择native

    mvn clean package -Pnative -DskipTests

    mvn的profile与spring的profile差异:https://www.cnblogs.com/sandyflower/p/11600058.html

  • 打native的docker镜像

    这里暂时先使用spring-boot-maven-plugin,通过mvn spring-boot:build-image来打包

    docker run --rm -p 8081:8081 demo:0.0.1-SNAPSHOT
    
# 语言 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×