Java Virtual Machine: GraalVM 21.3 baut auf Java 17 und bindet Schleifen um

Neben dem Update auf die aktuelle Java-Version bringt Oracles JVM-Implementierung Optimierungen beim Kompilieren und für native Images.

In Pocket speichern vorlesen Druckansicht 48 Kommentare lesen
Lesezeit: 4 Min.
Von
  • Rainald Menge-Sonnentag

Oracle hat das quartalsmäßige Update 21.3 der GraalVM veröffentlicht. Die Implementierung der Java Virtual Machine (JVM) arbeitet mit der jüngsten Java-Version 17 zusammen. Der Compiler hat einige Performance-Optimierungen für den Compiler an Bord. Außerdem sollen sich native Images schneller erstellen lassen.

Die Anbindung an Java 17 war zu erwarten, da die im September veröffentliche Version die erste mit Long-term Support (LTS) seit Java 11 ist. Mit Letzterer arbeitet GraalVM weiterhin zusammen. Für die Enterprise-Variante gibt es zusätzlich einen Build auf Basis von Java 8, aber die GraalVM Community Edition setzt lediglich auf OpenJDK 11 oder 17.

Der Compiler bringt in der Enterprise-Variante einige Optimierungen für Schleifen mit. Unter anderem bietet sie für sogenannte Non-counted Loops, also Schleifen ohne festen Zähler wie while-Blöcke, standardmäßig Strip Mining, eine Technik, um eine umfangreiche Schleife in mehrere kleinere Streifen (Strips) zu verschachteln. Daneben bietet sie Optimierungen für Schleifen, die als Endbedingung einen Vergleich mit dem Ungleich-Operator != haben wie

for (int i = start; i != end; i++){ ... }

Außerdem bietet der Compiler eine tiefere Prüfung, um unerreichbare Codesegmente zu erkennen, wie in folgendem Codebeispiel aus den Release Notes:

class A { ... }
class B extends A { ... }

if (x > 5) {
  if (y instanceof A) {
    throw Error();
  }
}
loop {
  int foo = <expensive computation>;
  if (x > 10) {
    if (y instanceof B) {
      bar(foo);
    }
  }
}

Dass der Aufruf von bar(foo) nie erreicht wird, ist erst auf den zweiten Blick zu erkennen. Die direkte Bedingung ist, dass x größer als 10 ist und y eine Instanz der Klasse B. Wenn diese Bedingungen zutreffen, greift aber bereits im Vorfeld das obere throw Error();, da in dem Fall x auch größer 5 und y eine Instanz von A ist: Die Klasse B ist eine Erweiterung der Klasse A.

Anders als die Vorgängerversionen erkennt GraalVM 21.3 den Zusammenhang und entfernt sowohl den Aufruf von bar(foo) als auch die Berechnung des Wertes für die Variable foo, die ausschließlich als Parameter des nun überflüssigen Aufrufs im Code zum Einsatz kommt.

Das Release bringt zudem einige Neuerungen für native Images, die GraalVM als Alternative zum Ausführen von Bytecode in der klassischen JVM bietet. Dafür erstellt ein Ahead-of-Time-Compiler (AOT) eigenständig ausführbare Dateien, die neben den übersetzten Klassen der eigentlichen Anwendung die Klassen der Runtime Library und der Dependencies sowie aus dem JDK statisch verlinkten Code enthalten.

Die Konfiguration ist in Version 21.3 erweitert und ermöglicht für Reflexion, JNI (Java Native Interface), Class-Path-Ressourcen und dynamische Proxy-Objekte, Bedingungen zur Erreichbarkeit von Klassen über "condition" : { "typeReachable" .. } zu definieren. In dem Fall bindet der Compiler die nachfolgenden Passagen nur dann ein, wenn die entsprechende Codepassage von anderem Code erreicht werden kann. Das Vorgehen reduziert potenziell die Größe des nativen Image.

Offensichtlich stehen eine verkürzte Build-Zeit und schlankere kompilierte Images ganz oben auf der Wunschliste der GraalVM-Nutzerinnen und -Nutzer. Das aktuelle Release führt Benchmarks zum Kompilieren der Beispielanwendung Spring PetClinic auf, bei denen auf einem AMD64-Laptop mit Linux und JDK 11 die Build-Zeit im Vergleich zu Version 21.2 von 163 Sekunden auf 133 Sekunden und die Imagegröße von 133 MByte auf 119 MByte gesunken sind.

Weitere Neuerungen unter anderem im Zusammenspiel mit WebAssembly lassen sich den Release Notes entnehmen. Die GraalVM ist sowohl als Enterprise-Variante als auch in einer Community Edition verfügbar. Für Letztere finden sich im GitHub-Reposiory Binaries für Linux, Windows und macOS auf Basis von Java 17 und Java 11.

(rme)