原標題: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
關注筆者公衆號,推送各種原創/優質技術文章 ⬇️