原标题:GraalVM – an introduction to the next level JVMjava
随着Red Hat宣布Quarkus做为…git
为GraalVM和HotSpot量身定制的下一代Kubernetes原生Java框架,使用一流的Java库和标准构建github
Red Hat展现的Quarkus示例项目的启动速度和内存消耗给我留下了深入的印象。使人印象深入的主要缘由之一是,代码是用GraalVM提早(ahead-of-time,AOT)编译成本机映像(native image)的。为了帮助您更好地了解传统的HotSpot JVM和GraalVM之间的区别,我将在此博客文章中向您介绍GraalVM及其功能和历史。json
TL; DR:GraalVM是Oracle开发的用纯Java编写的JVM扩展,支持多语言编程和提早编译。windows
多年来,HotSpot是Oracle维护和分发的主要Java虚拟机,用于运行Java程序。 Java HotSpot Performance Engine于1999年发布,最初由Animorphic开发,该公司被Sun Microsystems收购,如今由Oracle拥有。该虚拟机主要用C / C ++编写,而且变得愈来愈复杂(2007年估计有250.000行代码)。后端
HotSpot JVM的主要目的是运行Java字节码(.class文件)并持续分析程序的性能,以查找程序中常常执行的所谓热点,并即时(JIT,全称just-in-time)将其编译为本机代码(机器代码)以提升性能。这是在运行时完成的,而不是在Java程序执行以前执行的,所以是即时(just-in-time)的。bash
在HotSpot JVM中运行Java代码的工做流程以下所示(简化):架构
HotSpot虚拟机主要解释程序提供的Java字节码,但在程序运行过程当中发现有适合优化的部分时,也会及时将这部分字节码编译为机器代码。框架
当使用JIT编译器编译一个方法时,当该方法被调用时,jvm将直接执行编译出来的机器码,而不是解释它以此来提升性能。因为编译本机代码须要CPU时间和内存,JVM必须在运行时决定编译哪些方法,由于将全部方法直接编译为本机代码会影响性能。
借助Java 9,特别是JEP 295,JDK得到了提早(ahead-of-time,AOT)编译器jaotc。该编译器使用OpenJDK项目Graal进行后端代码生成,这样作的缘由以下:
JIT编译器速度很快,可是Java程序可能很是庞大,以致于JIT彻底预热须要很长时间。不多使用的Java方法可能根本不会被编译,因为重复的解释调用可能会致使性能降低
Graal OpenJDK项目演示了用纯Java编写的编译器能够生成高度优化的代码。使用此AOT编译器和Java 9,您能够提早手动编译Java代码。这意味着在执行以前生成机器代码,而不是像JIT编译器那样在运行时生成代码,这是第一种实验性的方法。
# using the new AOT compiler (jaotc is bundeled within JDK 9 and above) jaotc --output libHelloWorld.so HelloWorld.class jaotc --output libjava.base.so --module java.base # with Java 9 you have to manually specify the location of the native code java -XX:AOTLibrary=./libHelloWorld.so,./libjava.base.so HelloWorld
这将改善启动时间,由于JIT编译器没必要拦截程序的执行。这种方法的主要缺点是生成的机器代码依赖于程序所在的平台(Linux,MacOS,windows...)。这可能致使AOT编译代码与特定平台绑定。
基于Graal编译器,Oracle开始开发GraalVM,不只与HotSpots JVM的复杂C/C++代码库一块儿工做,并且还能够经过用Java编写的虚拟机解决当前的多语言迁移问题。
GraalVM的架构以下所示:
首先,您可能会注意到一些非JVM语言的存在。如今能够在这个通用虚拟机中运行Ruby、R或JavaScript代码。只是由于GraalVM采用了Truffle框架。Truffle是一个开源库,用于构建编程语言实现,做为自修改(self-modifying)抽象语法树的解释器。有了这个特性,您如今能够在Java代码库中编写和执行例如JavaScript代码。
此外,GraalVM提供了如下功能,能够提早将程序编译成本机可执行文件:
GraalVM容许您提早将程序编译为本地可执行文件。生成的程序不能在Java HotSpot VM上运行,而是使用必要的组件,例如内存管理,来自另外一种虚拟机实现的线程调度(称为Substrate VM)。SubstrateVM用Java编写,而后编译进本地可执行文件。与Java VM相比,生成的程序具备更快的启动时间和更低的运行时内存开销。
https://www.graalvm.org/docs/reference-manual/aot-compilation/
撰写本文时,GraalVM有两个版本:社区版(CE)和企业版(EE),仅适用于Mac OS X和Linux。要在开发过程当中在Windows上使用GraalVM,您可使用Oracle的官方Docker映像,如下示例中使用了该映像。
想象下面的简单HelloWorld类:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } }
在GraalVM和Java 9的AOT编译器以前,您执行了以下代码:
$ javac HelloWorld.java $ java HelloWorld Hello World!
借助GraalVM,您如今能够选择使用现有方式(HotSpot JVM)运行应用程序,或者使用GraalVM AOT编译器建立本机映像并运行可执行文件:
$ javac HelloWorld $ native-image HelloWorld $ ./helloworld HelloWorld!
在这个HelloWorld示例中,改进的性能是微不足道的,可是在更大和更现实的应用程序中,性能的改进是显著的。
在官方的GraalVM入门指南中能够找到一个简单的多语言应用程序示例:
import java.io.*; import java.util.stream.*; import org.graalvm.polyglot.*; public class PrettyPrintJSON { public static void main(String[] args) throws java.io.IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String input = reader.lines().collect(Collectors.joining(System.lineSeparator())); try (Context context = Context.create("js")) { Value parse = context.eval("js", "JSON.parse"); Value stringify = context.eval("js", "JSON.stringify"); Value result = stringify.execute(parse.execute(input)); System.out.println(result.asString()); } } }
这个Java类负责漂亮地打印JSON,使用JavaScript方法JSON.parse() 和JSON.stringify() 。此类的本机镜像可经过以下方式构建:
$ javac PrettyPrintJSON.java $ native-image --language:js PrettyPrintJSON $ ./prettyprintjson < prettyMe.json { "GraalVM": { "description": "Language Abstraction Platform", "supports": [ "combining languages", "embedding languages", "creating native images" ], "languages": [ "Java", "JavaScript", "Node.js", "Python", "Ruby", "R", "LLVM" ] } }
如今能够测量运行本机映像和在HotSpot中运行应用程序之间的性能差别:
$ time bin/java PrettyPrintJSON < prettyMe.json > /dev/null real 0m1.101s user 0m2.471s sys 0m0.237s $ time ./prettyprintjson < prettyMe.json > /dev/null real 0m0.037s user 0m0.015s sys 0m0.016s
在我看来,Oracle和GraalVM在Java做为编程语言的主导地位方面作得很是好。此外,这一举措提升了Java语言自己的可持续性和特性开发。有了多语言体系结构,这也增长了其余编程语言的采用。
您能够在个人GitHub存储库中找到示例,而后直接在GraalVM上(Mac和Linux)或在Windows上的Docker上(确保为Docker提供至少6 GB的RAM和2-4个内核)进行尝试。
原文地址:https://rieckpil.de/whatis-graalvm/
🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟
欢迎访问笔者博客:blog.dongxishaonian.tech
关注笔者公众号,推送各种原创/优质技术文章 ⬇️