Java 11

Mit Java 11 liefert Oracle endlich, was sich viele Entwickler vor einem Jahr erwartet hatten: eine stabile Java-Version mit Langzeitwartung (LTS = Long Time Support). Unter diesem Gesichtspunkt kann man Java 9 und Java 10 eigentlich nur als öffentliche Betas betrachten, bereits nicht mehr gewartet und aus heutiger Sicht obsolet.

An sich wäre das alles in Ordnung, wenn Oracle diesen Release-Prozess ehrlich und früh genug kommuniziert hätte …

Update 24.10.2018: Ich habe das Kleingedruckte in der Support-Dokumentation von Oracle bisher zu ungenau gelesen. Java 11 ist eine LTS-Version — aber nur für zahlende Oracle-Kunden. Ohne Vertrag gibt es von Oracle überhaupt keine LTS-Version von Java mehr! (Quelle 1, Quelle 2) Wer nicht zahlt, muss alle sechs Monate ein Versions-Update mitmachen oder auf von der Community gewartete Java-Releases auf OpenJDK-Basis ausweichen.

Aktuelle IntelliJ-Versionen sind bereits kompatibel zu Java 11

Long Term Support nur für zahlende Kunden

In der Support Roadmap verspricht Oracle zahlenden Kunden, Java 11 regulär bis September 2023 mit Updates zu versorgen. Der »Extended Support« reicht sogar noch drei Jahre länger. Was den Support betrifft, ist Java 11 für Oracle-Kunden somit der logische Nachfolger von Java 8.

Für »normale« Anwender ohne Support-Vertrag gibt es allerdings auch für Java 11 nur sechs Monate Updates!

Die kommenden fünf Java-Versionen 12 bis 16, die im Halbjahresrhythmus erscheinen werden, genießen wie Java 9 und 10 keinen Long Term Support. Sie sind also nur für Entwickler gedacht, die gerne die neuesten Features ausprobieren. Die nächste LTS-Version wird voraussichtlich erst wieder Java 17 sein (geplant für Herbst 2021, siehe auch dieses Diagramm eines Ubuntu-Entwicklers).

Neue Funktionen

Java 11 bietet eine Menge neuer Funktionen, die sich primär an fortgeschrittene Entwickler bzw. an das Enterprise-Lager richten. Zu den wichtigsten Neuerungen zählen:

  • Zwei neue Garbage Collectors (JEP 318 und JEP 333)
  • var-Deklaration auch für Lambda-Parameter (JEP 323)
  • Eine neue HTTP-Client-API (JEP 321)
  • Unterstützung für Unicode 10 (JEP 327)
  • Unterstützung für TLS 3 (JEP 332)
  • Zusätzliche kryptografische Funktionen (ChaCha20 and Poly1305, JEP 329)

Einfachere Java-Ausführung für Einsteiger

Die interessanteste Neuerung für Java-Einsteiger ist ein neues Konzept zur Ausführung von Java-Programmen, die aus nur einer einzigen Datei bestehen (Launch Single-File Source-Code Programs, JEP 330). Derartige Programme können nun einfach mit java Quellcode.java gestartet werden. (Bisher musste der Code bekanntlich zuerst mit javac kompiliert werden. Im zweiten Schritt musste an java der Klassenname ohne die Endung .java oder .class übergeben werden — ein Punkt, der bei Einsteigern oft für Verwirrung sorgt.)

Wenn Sie also die folgende Datei in einem Verzeichnis gespeichert haben …

// Datei HelloWorld.java
public class HelloWorld {
        public static void main(String[] args) {
                System.out.println("Hello World!");
        }
}

… dann können Sie den Code nun wie folgt ausführen:

java HelloWorld.java

Das ist eigentlich eine feine Sache! Das Kompilat wird dabei nicht dauerhaft gespeichert (es entsteht also keine neue Datei HelloWorld.class), sondern nur im RAM zwischengespeichert.

ACHTUNG Die Code-Ausführung funktioniert nur, wenn Sie das Programm nicht vorher schon kompiliert haben! Wenn es im aktuellen Verzeichnis bereits die Datei HelloWorld.class gibt, dann kommt es zur verwirrenden Fehlermeldung class found on application class path: HelloWorld. Mit anderen Worten: java weiß nicht, ob es nun HelloWorld.java kompilieren und ausführen soll, oder ob Sie eigentlich die bereits kompilierte Klasse HelloWorld.class ausführen möchten.

Zu diesem Konzept gibt es einige Varianten. Die Ausführung gelingt auch, wenn die Code-Datei nicht die Endung .java hat. In diesem Fall erfolgt der Aufruf mit der Option java --source n, wobei n die Java-Versionsnummer ist:

java --source 11 HelloWorld.txt

Linux- und macOS-Fans können den Java-Code sogar als Script verpacken. Die erste Zeile des Scripts muss in diesem Fall mit #!/pfad/zu/java --source 11 beginnen, also z.B.:

#!/usr/bin/java --source 11
// Datei HelloWorld.script
public class HelloWorld {
        public static void main(String[] args) {
                System.out.println("Hello World!");
        }
}

Nach chmod +x HelloWorld.script können Sie die Datei nun mit ./HelloWorld.script ausführen. Abermals scheitert die Ausführung, wenn es im gleichen Verzeichnis bereits die Datei HelloWorld.class gibt. Anstelle von #!/usr/bin/java ist auch die portablere Variante #!/usr/bin/env java erlaubt.

Einige weitere Varianten mit mehreren Klassen in einer Datei sowie mit der Verwendung von import sind in diesem Blog-Beitrag dokumentiert.

Neue Zeichenkettenfunktionen

In Java 11 stehen auch sechs neue Methoden zur Bearbeitung von Zeichenketten zur Verfügung:

  • s.repeat(n) dupliziert s n-mal
  • s.lines() liefert einen Stream mit den Zeilen der Zeichenkette
  • s.isBlank() liefert true, wenn die Zeichenkette leer ist oder nur aus Whitespace besteht
  • s.stripLeading(), s.stripTrailing() und s.strip() liefert eine neue Zeichenkette, in der der Whitespace am Beginn und/oder Ende eliminiert ist

Der Unterschied zwischen trim und strip besteht darin, dass strip komplett Unicode-kompatibel ist. Die folgenden Zeilen zeigen die Anwendung der neuen Funktionen in der jshell.

jshell> var s=" abc "
s ==> " abc "

jshell> s.strip()
$2 ==> "abc"

jshell> "abc".repeat(3)
$8 ==> "abcabcabc"

jshell> s="Hello\nWorld!"
s ==> "Hello\nWorld!"

jshell> var lines = s.lines()
lines ==> java.util.stream.ReferencePipeline$Head@5f2108b5

jshell> lines.forEach(System.out::println)
Hello
World!

JavaFX

JavaFX wurde aus Java 11 ausgegliedert. Das führt zur absurden Situation, dass die technologisch komplett veraltete Swing-Technologie weiter offiziell unterstützt wird, JavaFX aber nicht. Vielleicht sollte man es so formulieren: Nicht einmal Oracle glaubt daran, dass Java die richtige Sprache zur GUI-Entwicklung ist.

Persönlich finde ich das schade, weniger weil ich riesige JavaFX-Projekte entwickle, sondern mehr, weil JavaFX einen einfachen und eleganten Weg zur Realisierung einfacher Grafikprogramme bot. Im Unterricht macht die Programmierung eines kleinen Grafikprogramms viel mehr Spaß als die Entwicklung eines Programms, das Primzahlen ausspuckt.

JavaFX ist aber (noch) nicht (vollständig) tot. Vielmehr kümmert sich die Community nun um JavaFX, wobei die Firma Gluon dieKoordination übernommen hat. Zumindest für Version 11 hat das wunderbar funktioniert. JavaFX 11 wurde sogar eine Woche vor Java 11 freigegeben.

JavaFX steht auf der neuen Community-Website https://openjfx.io zum Download zur Verfügung. Für kommerzielle Kunden bietet Gluon Support-Verträge an.

Um also weiterhin JavaFX-Programme entwickeln zu können, müssen Sie das JavaFX SDK von hier herunterladen. Nach dem Auspacken der ZIP-Datei müssen Sie den Verzeichnisbaum an einen Ort verschieben, wo er für alle JavaFX-Benutzer zugänglich ist. Wenn JavaFX nur von einem einzelnen Benutzer verwendet wird, können Sie es auch im Home- oder Download-Verzeichnis belassen.

Um ein simples Hello-World-Programm zu kompilieren und auszuführen, sind die folgenden Anweisungen erforderlich (hier für macOS):

export FXPATH=/Users/kofler/Downloads/javafx-sdk-11/lib/
javac --module-path $FXPATH --add-modules=javafx.controls HelloFX.java 
java  --module-path $FXPATH --add-modules=javafx.controls HelloFX

Unter Linux gehen Sie gleich vor, der Pfad lautet dann aber /home/kofler/Downloads/....

Unter Windows ist die Syntax zur Definition und Nutzung von Umgebungsvariablen ein wenig anders. Verwenden Sie die folgenden Kommandos als Muster:

set FXPATH="C:\Users\kofler\Downloads\javafx-sdk-11\lib\"
javac --module-path %FXPATH% --add-modules=javafx.controls HelloFX.java 
java  --module-path %FXPATH% --add-modules=javafx.controls HelloFX

Um JavaFX in einem IntelliJ-Projekt ohne Maven, Gradle oder andere externe Tools zu verwenden, müssen Sie zwei Dinge tun:

  • Im Dialog File/Project Structure, Dialogblatt Modules/Dependencies wählen Sie mit dem Plus-Button JARs or directories aus und geben dann den Pfad zu Ihren lokalen JavaFX-Dateien an, also z.B. /Users/kofler/Downloads/javafx-sdk-11/lib/. Damit sollte IntelliJ im Quellcode alle javafx-Importe verstehen und in der Lage sein, das Programm zu kompilieren.

  • Im Dialog Run/Edit Configuration fügen Sie bei den VM options die folgenden zwei Optionen hinzu. (Dabei müssen Sie natürlich den Pfad durch den Ort auf Ihrem Rechner ersetzen.)

--module-path /Users/kofler/Downloads/javafx-sdk-11/lib --add-modules=javafx.controls,javafx.fxml
JavaFX-Bibliothek in IntelliJ hinzufügen
Erforderliche Optionen, damit IntelliJ ein JavaFX-Programm ausführen kann

Java 11 unter Linux

Ubuntu hat versprochen, die Java-Pakete in Ubuntu 18.04 automatisch auf Version 11 zu aktualisieren. Bisher ist das noch nicht der Fall. Ähnlich sieht es in der Beta für Ubuntu 18.10 aus. Die Paketnamen lauten zwar bereits openjdk-11-xxx, aber javac -version liefert 10.0.2. In der finalen Version von Ubuntu 18.10 steht Java 11 zur Verfügung.

Die Beta von Fedora 29 enthält immerhin schon eine Early-Access-Version von Java 11.

Wie gut JavaFX im Zusammenspiel mit Java 11 unter Linux funktioniert, werde ich mir ansehen, wenn es finale Versionen von Ubuntu 18.10 und Fedora 29 gibt.

Fazit

(hinzugefügt am 24.10.2018)

Professionelle Java-Entwickler, die im Oracle-Universum verankert sind und für den Java-Support zahlen, mögen mit dem neuen Release-Modell glücklich sein: Es gibt (endlich) wieder eine LTS-Version für alle, die Stabilität brauchen. Und es gibt halbjährliche Updates für jene, die immer die neuesten Features anwenden wollen.

Wer nicht zahlen will, und dazu zählen unzählige Bildungseinrichtungen, steht aber vor einem Dilemma: Halbjährliche Updates sind unmöglich zu administrieren. Auf der FH, an der ich unterrichte, läuft auf den Laborrechnern weiterhin Java 8 … Auf den Privatrechnern der Student(inn)en sind natürlich neuere Versionen installiert. Im Prinzip muss man mittlerweile davon ausgehen, dass jeder eine andere Java-Version verwendet. Das erschwert den Austausch von Code — z.B. in Form von Projekten einer IDE — enorm. Falsche oder fehlende PATH- und CLASSPATH-Einstellungen unter Windows erhöhen den Support-Aufwand weiter.

Java wird (zumindest im deutschen Sprachraum) noch immer recht oft als First Programming Language verwendet. Studenten lernen zuerst Java, dann andere Sprachen. Es ist Zeit, das zu ändern: Python ist als erste Sprache definitiv besser geeignet. Java ist ja an sich schon mit vielen Altlasten verbunden. Nun ruiniert Oracle mit seiner Update-Politik auch noch das Minimum an Stabilität, das gerade im Bildungsbereich erforderlich ist.

In einem zweiten Anwendungs-Segment von Java, der App-Programmierung für Android, nimmt der Zug zu Kotlin immer mehr Fahrt auf. Google hat auch wegen des jahrelangen Rechtsstreit mit Oracle großes Interesse daran, eine brauchbare Alternative zu Java zu etablieren.

Auch das Linux-Lager tut sich mit dem neuen Release-Modell schwer. Es bleibt abzuwarten, wie gut die langfristige Wartung eigener Java-Versionen auf Basis der OpenJDK gelingt. (Die Linux-Distributoren werden sich dabei wohl auf die LTS-Versionen konzentrieren.)

Gelingt es also Oracle tatsächlich, mit Java ein weiteres Open-Source-Projekt gegen die Wand zu fahren? Es sieht so aus.

Quellen und Links

JavaFX