Java 21 (LTS)
Java 21 (September 2023) ist eine LTS-Version. Zwischen Java 18 und 21 sind wichtige Sprach- und Plattform-Features gereift: von Vorschauen (Preview/Incubator) hin zu finalen Features. Diese Seite fasst die wichtigsten Highlights zusammen und zeigt kurze Beispiele.
- Virtual Threads (leichtgewichtige Threads) – Vorschau in 19/20, final in 21
- Pattern Matching für
switch– mehrere Vorschauen, final in 21 - Record Patterns – Vorschau 19/20, final in 21
- Sequenced Collections – neu in 21
- String Templates – Vorschau in 21
- Foreign Function & Memory API – mehrere Vorschauen bis 21
- Structured Concurrency – Vorschau in 21
- Generational ZGC – neu in 21
- Praktische Tools/Defaults: Simple Web Server (18), „UTF-8 by default“ (18)
Ein sehr einfacher, statischer Webserver für lokale Tests und Demos.
jwebserver --directory . --port 8000
Aufruf liefert statische Dateien aus dem aktuellen Verzeichnis aus.
Seit Java 18 ist UTF‑8 die Standard-Charset-Plattform. Das reduziert Encoding-Fallen über Plattformen hinweg.
Wesentliche Themen in 19 und 20 waren Vorschauen/Incubators, die in 21 finalisiert oder weitergeführt wurden:
- Virtual Threads (Project Loom) – Vorschau in 19/20
- Pattern Matching für
switch– weitere Vorschauen - Record Patterns – Vorschau (19) und zweite Vorschau (20)
- Foreign Function & Memory API – Vorschauen (19/20)
- Structured Concurrency – Incubator/Preview
- Vector API – fortgesetzter Incubator
Die folgenden Abschnitte zeigen die finalen Formen in Java 21.
Virtual Threads ermöglichen sehr viele nebenläufige Aufgaben mit minimalem Overhead – ideal für serverseitige I/O-lastige Workloads.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class VirtualThreadsDemo {
public static void main(String[] args) throws Exception {
try (ExecutorService es = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 1_000; i++) {
int id = i;
es.submit(() -> {
System.out.println("Task " + id + " auf " + Thread.currentThread());
// I/O-Operationen skalieren besonders gut
Thread.sleep(10);
return null;
});
}
}
}
}
Nutzen: kaum Blockierkosten pro Thread, einfache Migration von „klassischem“ Threading-Code.
switch kann jetzt auf Muster matchen und Variablen binden, inklusive Guard-Clauses (when).
class SwitchPatternDemo {
static String describe(Object o) {
return switch (o) {
case Integer i when i > 0 -> "Positive Zahl: " + i;
case Integer i -> "Nicht-positive Zahl: " + i;
case String s when s.isBlank() -> "Leerer String";
case String s -> "String (Länge=" + s.length() + ")";
case null -> "null";
default -> "Sonstiges: " + o.getClass().getSimpleName();
};
}
}
Nutzen: weniger instanceof/Casting, kompaktere Fallunterscheidungen.
Record-Objekte lassen sich direkt per Muster zerlegen. Verschachtelte Muster werden unterstützt.
record Point(int x, int y) {}
class RecordPatternDemo {
static int manhattan(Object o) {
return switch (o) {
case Point(int x, int y) -> Math.abs(x) + Math.abs(y);
default -> 0;
};
}
}
Nutzen: sehr prägnante, ausdrucksstarke Destrukturierung in Kontrollfluss.
Neue Interfaces wie SequencedCollection, SequencedSet und SequencedMap bieten definierte Reihenfolge-Operationen (getFirst, getLast, reversed …).
import java.util.*;
class SequencedDemo {
public static void main(String[] args) {
SequencedCollection<String> sc = new ArrayDeque<>();
sc.addFirst("A");
sc.addLast("B");
System.out.println(sc.getFirst()); // A
System.out.println(sc.getLast()); // B
System.out.println(sc.reversed()); // Ansicht in umgekehrter Reihenfolge
}
}
Nutzen: einheitliche API für Datenstrukturen mit Reihenfolge.
Saubere String-Interpolation mit Templates und Prozessoren.
// Vorschaubeispiel – erfordert Aktivierung der Preview-Features beim Kompilieren/Laufen
// javac --enable-preview --release 21 Demo.java
// java --enable-preview Demo
import static java.lang.StringTemplate.STR;
class StringTemplatesDemo {
public static void main(String[] args) {
int x = 7;
String s = STR."x = \{x}, x^2 = \{x * x}";
System.out.println(s);
}
}
Nutzen: sicherere, lesbarere String-Zusammensetzung als manuelles Konkatenieren oder String.format.
Die FFM-API ermöglicht Typsichere Interop mit „native“ Code (C-Bibliotheken) ohne JNI-Boilerplate sowie sichere Off-Heap-Speicherverwaltung.
Mini‑Beispiel (konzeptionell; reale Nutzung erfordert passende nativen Symbole):
// Preview-API; Kompilierung mit --enable-preview nötig
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
class FFMDemo {
public static void main(String[] args) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment seg = arena.allocate(4); // 4 Bytes Off-Heap
seg.setAtIndex(java.lang.foreign.ValueLayout.JAVA_INT, 0, 42);
int v = seg.getAtIndex(java.lang.foreign.ValueLayout.JAVA_INT, 0);
System.out.println(v); // 42
}
}
}
Nutzen: weniger JNI, klarere Speicherlebenszyklen, bessere Performance.
Vereinfacht die Koordination mehrerer Aufgaben, indem sie als Einheit behandelt werden.
// Preview-API
import java.util.concurrent.Callable;
import java.util.concurrent.StructuredTaskScope;
class StructuredConcurrencyDemo {
String fetch() throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Callable<String> a = () -> expensiveCall("A");
Callable<String> b = () -> expensiveCall("B");
var fa = scope.fork(a);
var fb = scope.fork(b);
scope.join();
scope.throwIfFailed();
return fa.resultNow() + "," + fb.resultNow();
}
}
static String expensiveCall(String id) throws InterruptedException {
Thread.sleep(50);
return id;
}
}
Nutzen: robuster paralleler Code mit klaren Abbruch- und Fehlersemantiken.
ZGC erhält eine Generationen-Variante, die kurzlebige von langlebigen Objekten trennt und so Durchsatz und Pausenzeiten weiter verbessert.
Aktivierung über JVM-Flags, z. B.:
java -XX:+UseZGC -XX:+ZGenerational ...
Mit Java 21 als LTS sind zentrale Themen wie Pattern Matching und Virtual Threads produktionsreif. Viele zuvor als Vorschau eingeführte Features sind konsolidiert; neue APIs (Sequenced Collections) und GC-Verbesserungen runden das Release ab. Projekte, die noch auf 17 LTS stehen, profitieren bei einem Upgrade vor allem von besserer Skalierbarkeit (Virtual Threads), prägnanterem Code (Pattern/Record Patterns, String Templates – sobald final) und moderneren Bibliotheken.