GraalVM startet durch

GraalVM: Oracles vielsprachige Virtual Machine im Java-Ökosystem

Wolfgang Weigend

Die GraalVM ist eine universelle Virtuelle Maschine (VM) für Anwendungen, die in den JVM-basierten Programmiersprachen Java, Scala, Kotlin, den dynamischen Sprachen JavaScript, R, Ruby, Python und LLVM-basierten Sprachen C/C++ geschrieben wurden. Sie ermöglicht die Sprachinteroperabilität in einer gemeinsamen Laufzeitumgebung und kann eigenständig oder im Kontext von OpenJDK, Node.js sowie der Oracle-Datenbank betrieben werden. Die GraalVM kann wahlweise als Open Source Community Edition (CE) oder als Enterprise Edition (EE) mit OTN-Lizenz verwendet werden.

Im Oktober 2019 wurde die auf dem JDK 8 Update 231 basierende GraalVM 19.2.1 veröffentlicht. Im November 2019 folgte die GraalVM 19.3.0 auf der Basis JDK 11 & JDK 8, mit Performance-Verbesserungen und polyglotter Unterstützung für verschiedene Programmiersprachen. Die ursprüngliche Entwicklung der GraalVM entstand vor mehreren Jahren in den Oracle Labs und führte zur ersten serienreifen Version GraalVM 19.0 im Mai 2019. Sie fügt sich nahtlos in das Java-Ökosystem ein und bietet mit ihrer Vielsprachigkeit eine Heimat für Programmiersprachen, die mit einem Bytecodecompiler ausgestattet sind. Die GraalVM verwendet das JDK 8 und kann mit dem JDK 11, OpenJDK 11 und höheren Versionen auf Command-Line-Ebene experimentell aktiviert werden:

java -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler –jar my_file.jar.

JDK mit JVM

Innerhalb des Java Development Kit (JDK) sind die Entwicklungswerkzeuge und der Java-Compiler javac angesiedelt. Die Ausführung von Java-Programmen übernimmt das Java Runtime Environment (JRE), entweder als eigenständige Ablaufumgebung oder als Bestandteil des JDK, inklusive der Java HotSpot Virtual Machine (JVM), wie in Abbildung 1 dargestellt. Der Class Loader lädt die erzeugten Java-Klassendateien, der Java-Bytecode wird verifiziert und im ersten Schritt ohne Optimierung vom Interpreter ausgeführt. Die Optimierung von Methoden übernimmt der JIT-Compiler, der anhand von Profiling gesammelten Ausführungsinformationen entscheidet, wie eine Methodenoptimierung durchgeführt werden kann, bevor der Maschinencode erzeugt wird. Die HotSpot VM beheimatet zwei JIT-Compiler, den C1-Client-Compiler zur Minimierung der Start-up-Zeit und den C2-Server-Compiler, mit dem Fokus auf Durchsatzsteigerung und für dauerhafte Performanceverbesserungen. Der C2-Compiler soll den ausgeführten Code intensiv analysieren und die dabei erkannten Optimierungen besser in Maschinencode umsetzen können.

Abb. 1: Java Runtime mit JVM

JIT-Compiler mit Tiered Compilation und Graal-Compiler

Beim C1-Client-Compiler kann die Tiered Compilation, durch java –client -XX:+TieredCompilation aktiviert werden, aber der C2-Server-Compiler läuft ohne Tiered Compilation. Die Tiered-Compilation-Ausführungs-Level sind wie folgt definiert:

Level 0: interpretierter Code, Level 1: einfacher C1-kompilierter Code ohne Profiling, Level 2: eingeschränkter C1-kompilierter Code mit geringem Profiling, Level 3: vollständiger C1-kompilierter Code mit komplettem Profiling und Level 4: C2-kompilierter Code, der die Profile-Daten der vorherigen Schritte benutzt. Das Java Virtual Machine Compiler Interface (JVMCI) ermöglicht den Austausch vom bisherigen C2-Compiler, der in C++ implementiert wurde (Abb. 2), durch den vollständig in Java geschriebenen Graal-Compiler (Abb. 3). Mit der neuen Just-in-time-Compilertechnologie werden Java-Programme schneller ausgeführt und der optimierte JIT-Compiler übernimmt die Umwandlung vom Java-Bytecode zum Maschinencode. Vorteilhaft ist dabei, dass die Speicherallokierung direkt auf dem Java Heap erfolgt und dass der Bootstrap-Mechanismus begünstigt wird, da der optimierte Graal-Compiler als Bestandteil der JVM in einer Sprache geschrieben ist, die auch die JVM ausführt.

Abb. 2: HotSpot VM implementiert mit C++

Abb. 3: GraalVM mit Graal-Compiler in Java

Polyglotte GraalVM

Neben den JVM-basierten Sprachen können auch andere Sprachen, die mit dem GraalVM Language Implementation Framework implementiert wurden, direkt von Java aus aufgerufen werden (Abb. 4). Die Ausführung von dynamischen Sprachen JavaScript, R, Ruby, Python erfolgt über das Truffle Language Implementation Framework, mit einem API für Sprachinterpreter (Abb. 5). Truffle ist ein Language-Abstract-Syntax-Tree-Interpreter, der es ermöglicht, andere Sprachen mit der GraalVM auszuführen. Die LLVM-basierten Sprachen C/C++ werden über den LLVM-Bitcode-Interpreter Sulong eingebunden. Sulong ist in Java geschrieben und verwendet das Truffle Framework und Graal als dynamischen Compiler. Mit Sulong kann man C/C ++, Fortran und andere Programmiersprachen, die in LLVM-Bitcode umgewandelt werden können, mit der GraalVM ausführen. Um ein Programm auszuführen, muss das Programm mit einem LLVM Frontend wie clang zu LLVM-Bitcode kompiliert werden.

Abb. 4: HotSpot VM mit Graal für JVM-Sprachen

Abb. 5: HotSpot VM mit Graal für dynamische Sprachen

GraalVM Native Image

Mit der GraalVM können native Images erzeugt werden und diese nativen Binaries werden direkt im Betriebssystem ausgeführt, ohne die JVM benutzen zu müssen. Bei der Native-Image-Erzeugung wird eine statische Analyse angewandt, um jeglichen Code zu finden, der über die Java-Main-Methode erreichbar ist, und um dann eine vollständige AOT-Kompilierung (AOT) durchzuführen. Die resultierende native Binärdatei enthält das gesamte Programm zur Ausführung in Maschinencode (Abb. 6) und durch den optimierten AOT-Compiler werden schnellere Start-up-Zeiten erreicht. Das native Binary kann mit anderen nativen Programmen verknüpft werden und optional den GraalVM-Compiler für die zusätzliche JIT-Kompilierungsunterstützung enthalten, um andere, auf GraalVM basierende Sprachen, auszuführen. Zur Leistungssteigerung können native Images mit profilgesteuerten Optimierungen erstellt werden, die bereits in einer früheren Anwendungsausführung gesammelt wurden.

Abb. 6: GraalVM Native Image

Für die Java-Programmausführung der GraalVM ist die Substrate VM zuständig, die aus Java-Anwendungen über AOT-Kompilierung native Binärdateien erzeugt und die Laufzeitaspekte wie Threads und Speicher verwaltet. Das Substrate VM Framework benötigt die Installation von mx und den auf ein JVMCI-fähiges JDK 8 gesetzten JAVA_HOME-Pfad, um die AOT-Kompilierung von Java-Applikationen zu beginnen. Das in Python geschriebene Command-Line-Tool mx dient zur Verwaltung der Entwicklung von Java-Code. Es enthält einen Mechanismus zum Spezifizieren von Abhängigkeiten sowie zum Erzeugen, Testen, Ausführen und Ändern des Codes als auch der erstellten Artefakte. Das Tool mx enthält Entwicklungsunterstützung für Code, der auf mehrere Quell-Repositories verteilt ist.

Die Native-Image-Kompilierung ist abhängig von der lokal eingesetzten Toolchain, d. h. glibc-devel, zlib-devel (Headerdateien für die C-Bibliothek und zlib) und gcc müssen auf dem System verfügbar sein. Das Erstellen von Images unter Windows ist noch experimentell. Unter Windows muss Python 2.7, Git for Windows und das Windows SDK for Windows 7 installiert sein. Alle Builds müssen über den Windows SDK 7.1 Command Prompt ausgeführt werden. Nach dem Repository Cloning kann das „Hello World“-Beispiel in Listing 1 ausgeführt werden.

cd substratevm
mx build    // Compile all Java and native code

echo "public class HelloWorld { public static void main(String[] args) { System.out.println(\"Hello World\"); } }" > HelloWorld.java
$JAVA_HOME/bin/javac HelloWorld.java
mx native-image HelloWorld
./helloworld

Die GraalVM-Source-Repository-Komponenten auf GitHub:

  • GraalVM Standard Development Kit (SDK) (Kasten „GraalVM SDK“) ist eine API-Sammlung der GraalVM.
  • GraalVM-Compiler: geschrieben in Java, getrimmt auf hohe Leistung und Erweiterbarkeit, der sowohl die dynamische als auch die statische Kompilierung unterstützt. Der Compiler kann in die Java HotSpot VM integriert sein oder eigenständig ausgeführt werden.
  • Truffle Language Implementation Framework: ebenfalls in Java geschrieben, bildet die Basis zur Unterstützung von anderen Sprachen. Über ein Truffle API können Programmierspracheninterpreter gebaut werden, die über die GraalVM ausführbar sind. Truffle ist eine Open-Source-Bibliothek zum Erstellen von Programmiersprachenimplementierungen als Interpreter für selbstmodifizierende Abstract Syntax Trees (AST). Die wachsende Anzahl von gemeinsam genutztem Implementierungscode senkt den Sprachimplementierungsaufwand signifikant, und von Vorteil ist ein universelles Instrumentierungs-Framework, das mehrsprachiges Debugging und andere externe Entwicklungswerkzeuge unterstützt.
  • Graal-Tool-Set zur GraalVM-Sprachimplementierung mit dem Instrumentation-Framework, basierend auf Truffle, ist sprachunabhängig. Die Tools können mit jeder Sprache verwendet werden, die mit Truffle implementiert wurde, sowie die Tests mit dem Technology Compatibility Kit (TCK) erfolgreich durchlaufen hat.
  • Substrate VM Framework zur AOT-Kompilierung von Java-Anwendungen in ausführbare Images oder gemeinsam genutzte Objekte, erstellt unter den Bedingungen einer festgelegten und abgeschlossenen Umgebung.
  • Sulong Engine zum Ausführen von LLVM-Bitcode auf GraalVM. Sulong ist in Java geschrieben und verwendet das Truffle-Implementierungs-Framework und Graal als dynamischen Compiler.
  • TRegex ist eine Implementierung eines Subsets regulärer ECMAScript-Ausdrücke, die mit dem GraalVM-Compiler und dem Truffle API reguläre Ausdrücke ausführen können.
  • VM Suite beinhaltet Komponenten zur Erstellung eines modularen GraalVM Image. Die VM ermöglicht die Erzeugung von benutzerdefinierten GraalVM-Distributionen sowie installierbare Komponenten. Die definierte GraalVM-Basisdistribution enthält ein JVMCI-fähiges JDK, das GraalVM SDK, Truffle und den GraalVM-Komponenteninstaller. Weitere Komponenten können über den dynamischen Suite-Import hinzugefügt werden.

GraalVM SDK

  • org.graalvm.polyglot-Module beinhalten APIs zum Einbinden von Graal-Sprachen in Java-Host-Applikationen.
  • org.graalvm.collections-Module beinhalten Memory-effiziente Common-Collection-Datenstrukturen, die übergreifend von Graal Projekten benutzt werden.
  • org.graalvm.options-Module beinhalten wiederverwendbare Klassen als Option.

GraalVM Open Source

Die GraalVM Community Edition basiert auf 3,6 Millionen Open-Source-Codezeilen, die vom GraalVM-Team und anderen Entwicklern stammen, sowie auf zusätzlichen Millionen Source-Codezeilen aus Projekten, auf die GraalVM angewiesen ist, wie Java, Node.js und andere (Abb. 7).

Abb. 7: 3,6 Millionen Open-Source-Codezeilen aktiv gewartet für GraalVM

Versionsauswahl und Installation

Die GraalVM gibt es in zwei Ausführungen: Zum einen gibt es die frei einsetzbare Open Source GraalVM Community Edition, die aus den GraalVM GitHub Sourcen erstellt und als vorgefertigte Binärdatei für Linux-, macOSX- und für die Windows-Plattformen auf x86-64-Bit-Systemen angeboten wird. Die Windows-Unterstützung ist experimentell. Die Lizenzierung der Open-Source-Komponenten ist im Kasten „Lizenzierung der GraalVM-Komponenten“ dargestellt.

Lizenzierung der GraalVM-Komponenten

  • Truffle Framework mit seinem abhängigen GraalVM SDK ist lizenziert unter der Universal Permissive License
  • Tools Project ist lizenziert unter der GPL 2 mit Classpath Exception
  • TRegex Project ist lizenziert unter der GPL 2 mit Classpath Exception
  • GraalVM-Compiler ist lizenziert unter der GPL 2 mit Classpath Exception
  • Substrate VM ist lizenziert unter der GPL 2 mit Classpath Exception
  • Sulong ist lizenziert unter 3-clause BSD
  • VM ist lizenziert unter der GPL 2 mit Classpath Exception

Zum anderen gibt es die optimierte GraalVM Enterprise Edition, die für den produktiven Einsatz kostenpflichtig ist und nur über die Oracle-Technology-Network-Lizenzvereinbarung (OTN-Lizenz) angeboten wird. Im Gegensatz zur Community Edition bietet die GraalVM Enterprise Edition eine verbesserte Leistungsfähigkeit, Sicherheit und Skalierbarkeit, die für den Produktivbetrieb von Anwendungen relevant sind. Die GraalVM Enterprise Edition ist für Entwicklung, Test, Prototyping und Demozwecke kostenlos und kann als Binärdatei für Linux-, MacOS X- und für die Windows-Plattformen auf x86-64-Bit-Systemen vom Oracle Technology Network heruntergeladen werden. Die Windows-Unterstützung ist experimentell (Kasten „GraalVM EE 19.2.1 unter MS Windows 10“).

Die GraalVM-Installation ist in wenigen Minuten vollzogen und wird als *.tar.gz- oder *.zip-Archivdatei heruntergeladen und in ein Verzeichnis entpackt. Dort muss die Variable JAVA_HOME auf den Pfad mit dem verwendeten JDK gesetzt sein.

Die Grundinstallation der GraalVM EE beinhaltet die JVM, den GraalVM-Compiler, den LLVM-Bitcodeinterpreter und die JavaScript-Laufzeitumgebung mit Node.js-Unterstützung.

GraalVM EE 19.2.1 unter MS Windows 10
C:\graalVM\bin>java -version
java version „1.8.0_231“
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit GraalVM EE 19.2.1 (build 25.231-b11-jvmci-19.2-b03, mixed mode)

Performance

Messungen der GraalVM mit einer Cloud-Infrastructure haben ergeben, dass die Compiler-Optimierungen der GraalVM Enterprise Edition Version 19.1 die Objektallokierungen reduzieren und dass sich die Ausführungsgeschwindigkeit vom Cloud-Monitoring-Service gegenüber dem JDK 8 verbessert.

Als Resultat sind weniger Garbage-Collection-Pausen bei geringerem Rechenleistungsverbrauch für die äquivalente Workload-Ausführung nachweisbar. Der Cloud-Monitoring-Service konsumierte insgesamt fünf Prozent weniger Prozessorleistung, erzielte einen höheren Durchsatz und verbrauchte weniger Zeit für die Garbage Collection und andere Systemaktivitäten. Beim Monitoring-Service wurden im Vergleich zu Java 8 Update 212 die Garbage-Collection-Zeit um 25 Prozent minimiert und die Applikationspausenzeiten um 17 Prozent verringert. Der Durchsatz erhöhte sich um zehn Prozent mit den GraalVM-Optimierungen bei der Anzahl der Transaktionen pro Sekunde im Vergleich zu Java 8 Update 212.

Fazit

Bei aller Euphorie angesichts der innovativen und polyglotten GraalVM mit ihren ungeahnten Einsatzmöglichkeiten muss sich die Praxistauglichkeit dieser jungen Technologie erst bewähren. Die GraalVM-AOT-Compiler-Fähigkeit zur Erstellung von eigenständig ausführbaren Native Images und ihre – gegenüber der JVM – verbesserte Start-up-Zeit bei geringerem Memory-Verbrauch lassen es zu, dass Java in den Bereich der Systementwicklung vordringen kann. Zudem gelangen die Vorteile der GraalVM Native Images direkt zu den Java Microservices Frameworks.

Mit der neuen GraalVM und der darin enthaltenen nativen Image-Funktionalität können auch kleinere und leistungsfähigere JavaFX-Anwendungen mit der aktuellen, ein Cross-Plattform-Deployment ermöglichenden JDK-Version und der korrespondierenden JavaFX-Version erstellt werden.

Insgesamt hat die GraalVM das Potenzial, die Java-Landschaft grundlegend zu verändern. Das könnte sich im Segment Mobile- und Embedded-Technologie bemerkbar machen. Auch die Entwicklungsbeiträge zum Ökosystem mit GraalVM und gemeinsamen Open-Source-Projekten haben zugenommen, wie Eclipse Vert.x Tool-Kit, Fn Project, Gluon Client Plugin, Helidon, Micronaut, Picocli Java Command Line Parser und Quarkus zeigen.

Geschrieben von
Wolfgang Weigend
Wolfgang Weigend
Wolfgang Weigend arbeitet als Sen. Leitender Systemberater bei der Oracle Deutschland B.V. & Co. KG. Er beschäftigt sich mit Java-Technologie und -Architektur für unternehmensweite Anwendungsentwicklung.
Kommentare

Hinterlasse einen Kommentar

avatar
4000
  Subscribe  
Benachrichtige mich zu: