Oracle下世代虚拟机GraalVM-介绍篇

2,660 阅读4分钟

GraalVM 是 Oracle 发布的下世代 Java 虚拟机,2019.05 才发布了第一个 release 版本,分别有社区版和企业版

GraalVM 三大特点

1. 高效能运行 Java

使用 GraalVM 执行 Java 程式可以变得更快. GraalVM 之所以能够更高效能运行 Java 应用,是因为使用到了 Graal 编译器技术,而 Graal 编译器是一个 JIT 编译器,但什么又是 JIT 编译器呢?

实际上,在 Java 里的编译器可以分为[前端编译器]和运行期编译器,前端编译器是指将 .java 编译成 .class 的过程,而运行期编译器则是指将 .class 字节码转变成机器码的过程,而运行期编译器的英文为 Just In Time Compiler,所以又能简称为 JIT 编译器

当初 JVM 开发团队把大部分的代码优化都放在运行期的编译器 JIT 上,而前端的编译器 javac 几乎没有任何代码优化措施,原因是因为这样可以让那些不是由 javac 产生的 .class 文件,也能享受到编译器优化所带来的好处,而前端编译器 javac 则专门负责处理 Java 的语法糖,将他转换为正常的字节码,因此可以说前端编译器 javac 是负责增进程序员开发效率,而运行其编译器 JIT 则是负责增进代码运行速度

  • 前端编译器 Javac : 负责将java中的语法糖,转换为正常的字节码
  • [运行器编译器] JIT : 负责代码优化

image.png

了解了 JIT 编译器之后,我们说回到 Graal 编译器这里

Graal 编译器是使用 Java 写的 JIT 编译器,虽然难免会让人联想到性能会比不上 HotSpot 使用 C++ 写的 C2 编译器,但是在各种实验之后,得到的数据显示对于 Java 应用而言,Graal 编译器和 C2 编译器的能力几乎不相上下(在已经预热完毕的前提下)

而对于 Scala 应用来说,Graal 编译器更是能达到 10% 以上的优化,这也是为什么 Twitter 大规模的使用 GraalVM 替换掉原本的 HotspotVM

image.png

2. 多语言并行

可以在 Java 里面同时使用多种语言,像是 JavaScript、R...(包括跑在jvm和不是jvm上的语言都可以) 个人感觉这个在大多数中国企业里使用场景没那么多,大部分都是比较单一的语言使用就足够了,对我来说这个功能比较鸡肋。

3. 快速启动

GraalVM 还有最后一项技术,就是 native image 快速启动,这项技术是在编译期时,就将 Java 应用直接编译成[二进制]的机器码,让这个程式可以像一般二进制的档案被运行

[native image] 带来的好处是可以更快速的启动一个 java 应用,以往如果要启动 java 程式,需要先启动 jvm 再载入 java 代码,然后再即时的将 .class 字节码编译成机器码,交给机器执行,非常耗时间和耗内存,而如果使用 native image,可以取得一个更小更快速的镜像,适合用在云部署上

native image 之所以可以快速启动,是因为他底层使用了 Ahead-of-time compile(提前编译),也就是说,他在编译期时,会把所有相关的东西,包含一个基底的 VM,一起编译成机器码,这个基底 VM 是 GraalVM 内部才有的东西,他只包含最基本的线程排成机制、垃圾回收,尽可能的缩小必要的 jvm 体积

虽然 native image 听起来很厉害,但是他也有不可抹灭的缺点,就是使用 native image 的程式,吞吐量会下降,原因是因为 java 程式很大一部分的优化都在 JIT 编译器中,而 native image 是没有使用到任何 JIT 提供的好处的,还有另一个缺点是,native image 并没有办法动态的加载类(因为所有东西必须要在编译期就决定好),所以也没办法使用反射等相关机制

不过对于这个问题,GraalVM 也有提出相对应的解法,就是在编译时,把所有可能的类全部编译进来,所以反射机制还是可以支持的,不然的话,整个 Spring framework 就不能使用 native image 了。目前 Spring 5 也打算开始支持 GraalVM native-image 的开箱即用设定,可以想像无服务器计算的 java 应用可能是之后的趋势,毕竟要有 native image 的快速启动特性,才能够达到无服务器计算的初衷