GraalVM: (die Zukunft von Java)
tarent Blog

GraalVM: (die Zukunft von Java)

23.09.2020 Posted 1 Monat ago Titian Horvath

Um den Technologie-Stack der tarent immer auf dem aktuellen Stand zu halten, evaluieren wir permanent neue Technologien um diese gegebenenfalls in Projekten zu nutzen. Aktuell machen wir das in Form eines Beispiel-Projektes – der “Corona-Bäckerei”. Hier erproben wir verschiedenste Technologien am immer selben Projekt und vergleichen diese. In meinem Blog geht es aber nicht um ein bestimmtes Framework, sondern um GraalVM.

GraalVM: Was ist das?

GraalVM (General Recursive Applicative and Algorithmic Language) ist ein Werkzeug für Entwickler zum Schreiben und Ausführen von Java-Code. Genauer gesagt ist GraalVM eine von Oracle entwickelte Java Virtual Machine (JVM) und ein Java Development Kit (JDK). Es handelt sich um eine hochleistungsfähige Laufzeitumgebung, die Verbesserungen der Anwendungsleistung und -effizienz bietet.

Die Ziele von GraalVM sind griffig:

  • das Schreiben eines Compilers, der schneller und einfacher zu warten ist
  • die Verbesserung der Leistung von Sprachen, die auf der JVM laufen
  • die Verkürzung der Startzeiten von Anwendungen
  • die Unterstützung anderer Sprachen im Java-Ökosystem
  • sowie die Bereitstellung einer Reihe von Programmierwerkzeugen für diesen Zweck.

 

Das Projekt startete 2014 zunächst als Forschungsprojekt und wird seit 2017 von Twitter produktiv eingesetzt. Für die breite Öffentlichkeit wurde es aber erst in der zweiten Hälfte des Jahres 2019, nach viel Feedback und dutzenden gemeldeter und gefixter Probleme, mit der Version 19 langsam produktionsreif.

Der Compiler

Um die Unterschiede zu verstehen, mache ich erst einmal einen kleinen Exkurs, um zu beschreiben, wie der Compiler normalerweise arbeitet:
Java-Quellcode wird zur Ausführung zunächst in plattformunabhängigen Java-Bytecode übersetzt. Anschließend wird er von einer Java Virtual Machine (JVM) ausgeführt, mit Hilfe des Just-In-Time (JIT) Compilers in Maschinencode übersetzt, im Speicher abgelegt und ausgeführt. Die Referenzimplementierung der JVM ist die Hotspot-JVM des OpenJDK. Diese nutzt den so genannten C2-JIT-Compiler, welcher mittlerweile sehr alt und schwer wartbar geworden ist. Deshalb war das Ziel des GraalVM-Teams möglichst sämtlichen Code in Java und nicht in C++/ Assembler zu schreiben.

GraalVM Compiler

Im Vergleich zu einer Standard-JVM bietet GraalVM einen verbesserten JIT-Compiler als Ersatz für den betagten C2 und eine aggressivere Garbage Collection. Dadurch kann eine höhere Leistung bei einem geringeren Speicherbedarf erzielt werden. Dies ist insbesondere für langlebige Serveranwendungen interessant.

Der Compiler kann zusätzlich als Ahead-of-Time(AOT)-Compiler für die GraalVM-Native-Image-Funktion verwendet werden. Hierbei wird die gesamte Anwendung mit allen notwendigen Abhängigkeiten zu einer in sich geschlossenen binären Datei vorkompiliert. Dies verbessert die Startzeiten und den Speicherbedarf der Anwendung erheblich.

GraalVM Native Image verwendet eine andere Art der Ausführung von Java-Programmen als Benutzer der Java HotSpot VM gewohnt sind. Es wird zwischen Image-Build-Time und Image-Run-Time unterschieden. Zur Image-Build-Zeit findet eine statische Analyse aller Methoden, die vom Einstiegspunkt der Anwendung aus erreichbar sind statt. Diese (und nur diese) Methoden werden dann im Voraus in das native Image kompiliert. Aufgrund des unterschiedlichen Optimierungsmodells können sich Java-Programme etwas anders verhalten, wenn sie in ein natives Image kompiliert werden.

Tracing Agent

Es wurde daher der Tracing Agent implementiert, um einige Einschränkungen von GraalVM Native Images zu überwinden und den Konfigurationsprozess zu vereinfachen. Er zeichnet das Verhalten einer Java-Anwendung auf, die auf GraalVM oder einer anderen kompatiblen JVM läuft, die das Java VM Tool Interface (JVMTI) unterstützt.

Er hilft beim Umgang mit Funktionen wie Reflection, Java Native Interface, Class Path Resources und Dynamic Proxies in der GraalVM-Umgebung. Er kommt dann zum Einsatz, wenn die statische Analyse nicht automatisch bestimmen kann, was in ein natives Image eingefügt werden soll. Unentdeckte Verwendungen dieser dynamischen Merkmale müssen dem Generierungsprozess in Form von Konfigurationsdateien zur Verfügung gestellt werden. Deshalb beobachtet der Tracing Agent das Anwendungsverhalten und baut Konfigurationsdateien auf.

Polyglotte VM

Die GraalVM erlaubt mehrere verschiedene Programmiersprachen innerhalb einer Anwendung. Sie ist also mehrsprachig (auch polyglott genannt). Neben Java-Code wird auch Scala, Kotlin, Groovy, Clojure, R, Python, JavaScript und Ruby unterstützt. Im Wesentlichen ermöglicht GraalVM Entwicklern die effiziente Ausführung von Code in mehreren Sprachen und Bibliotheken in einer einzigen Anwendung.

Polyglotte VM Quelle: https://jaxenter.de/neuer-compiler-fuer-jvm-graalvm-83252

Frameworks

Die GraalVM Native Images werden aktuell von folgenden Microservice-Frameworks voll unterstützt: Quarkus, Micronaut, Helidon

Graph: Microservice Startup Time

Frameworks

Quelle: https://www.graalvm.org/why-graalvm/#for-microservices-frameworks

Spring Framework

Aktuell ist Spring GraalVM Native Image Support noch unter “Heavy Development” und es ist absehbar, dass sich dort noch einiges tun wird.

Kleinere, weniger komplexe Anwendungen lassen sich allerdings schon mehr oder weniger Problemlos zu Native Images kompilieren, wobei Verbesserungen der Performance ähnlich der obigen Grafiken zu beobachten sind. Bei größeren Anwendungen ist es jedoch noch viel zu aufwändig und konfigurationsbedürftig, als dass es praktikabel nutzbar wäre.

Die Entwickler haben zudem in einem Blogpost angekündigt, dass im Oktober mit Spring 5.3 nativer Support für GraalVM Images kommen soll. Außerdem wurde gesagt, dass man zukünftig auch ältere/schon bestehende Anwendungen leicht als native Image laufen lassen können soll, ohne alles umbauen zu müssen.

Fazit

Das GraalVM Projekt ist meiner Meinung nach ein lang ersehntes Feature vieler (Java) Entwickler, da die momentanen JVM-Implementationen bekanntlich nicht gerade ressourcenschonend arbeiten. Es hebt die Sprache auf ein neues Level, auf dem sie auch mit moderneren Sprachen locker mithalten kann. Gerade die Interoperabilität mit vielen Sprachen und deren schier endlosen Bibliotheken könnte viel frischen Wind in die Sache bringen. Ich denke, dass Oracle damit die weitere Nutzung von Java für die nächsten Jahre gesichert hat.

Als Ersatz für die Hotspot-JVM kann sie schon heute produktiv genutzt werden und bringt erhebliche Verbesserungen gegenüber den anderen JVMs. Das interessanteste Feature, das Native Image, ist zum aktuellen Zeitpunkt mit den o.g. Frameworks schon sehr gut, sogar Out-of-the-Box nutzbar. Ich warte gespannt auf den im Oktober angekündigten Spring Release und freue mich darauf es hoffentlich schon bald in der tarent zu nutzen.