As of: February 2026
Typical Starting Point
- Java 6 to 8, Swing for desktop GUIs
- A single JVM/JDK source: Oracle (formerly Sun Microsystems)
- Maven as build tool
- IDE: NetBeans, Eclipse, IntelliJ IDEA
1. The Java Landscape Has Changed Fundamentally
1.1 Release Cycle
The biggest structural change: Java now ships every 6 months (March and September). Every 2 years there is a Long-Term Support (LTS) release with at least 3 years of updates.
Starting point (2014) Today (2025/2026)
──────────────── ──────────────────
Java 8 (LTS, 2014) Java 25 (current, LTS, Sep 2025)
Next version: wait ??? years New version every 6 months
One provider: Oracle/Sun Dozens of JDK distributions
JRE separately installable JRE no longer exists separately
1.2 The LTS Versions (Key Milestones)
| Version | Year | Status | Most Important Innovation |
|---|---|---|---|
| Java 8 | 2014 | Common starting point — still widely used | Lambdas, Streams, Optional |
| Java 9 | 2017 | Non-LTS | Module System (Project Jigsaw) |
| Java 11 | 2018 | LTS | var in lambdas, HTTP client, JRE removed |
| Java 17 | 2021 | LTS | Sealed Classes, Records, Pattern Matching |
| Java 21 | 2023 | LTS ⭐ (current recommendation) | Virtual Threads, Pattern Matching for switch, Record Patterns |
| Java 25 | Sep 2025 | LTS ⭐ (current) | Further stabilisations |
Recommendation: Java 21 is the current LTS and should be used for new projects. Java 8 and 11 are still heavily present in legacy projects.
2. JDK Distributions: Oracle Is No Longer the Only Provider
2.1 What Happened?
After Oracle acquired Sun Microsystems (2010), Oracle changed the licensing policy multiple times. Since 2019, the Oracle JDK has been paid for commercial use (with occasional relaxations). This led to many alternative JDK distributions emerging — all based on the open OpenJDK source code.
2.2 The Most Important JDK Distributions
| Distribution | Provider | Cost | Distinguishing Feature |
|---|---|---|---|
| Eclipse Temurin | Eclipse Foundation (Adoptium) | Free | ⭐ Recommendation. Community-driven, TCK-tested, backed by IBM/Red Hat/Microsoft |
| Amazon Corretto | Amazon | Free | Optimised for AWS cloud, LTS support |
| Oracle JDK | Oracle | Free for development, paid for production (changing licences!) | The "original" build |
| Oracle OpenJDK | Oracle | Free | Reference implementation, only 6 months of support per version |
| Azul Zulu | Azul Systems | Community version free | Very broad platform support |
| Microsoft OpenJDK | Microsoft | Free | Optimised for Azure |
| Red Hat OpenJDK | Red Hat | Free (RHEL) | Standard on RHEL/Fedora/CentOS |
| BellSoft Liberica | BellSoft | Free | Only distribution with built-in JavaFX |
| SAP Machine | SAP | Free | Optimised for SAP environments |
| IBM Semeru | IBM | Free | Uses OpenJ9 instead of HotSpot (alternative JVM) |
| GraalVM | Oracle | Community version free | Ahead-of-time compilation, native images, polyglot |
2.3 Which Distribution to Choose?
The recommendation is: Eclipse Temurin (formerly AdoptOpenJDK). It is the de facto standard for OpenJDK distributions, completely free, TCK-tested, and supported by all major IDEs.
Installation via SDKMAN (recommended — manages multiple Java versions):
# Install SDKMAN
curl -s "https://get.sdkman.io" | bash
# Install Java 21 (Temurin)
sdk install java 21.0.4-tem
# Switch between versions
sdk use java 21.0.4-tem
sdk use java 17.0.12-tem
# Show all available distributions
sdk list java
2.4 The JRE No Longer Exists
Since Java 11, Oracle no longer ships a separate JRE. Instead, there is jlink, a tool that creates a custom runtime containing only the required modules — significantly smaller than a full JRE.
3. The Most Important Syntax Innovations (Java 9 to 21)
3.1 Comparison: Old vs. New Code
// ══════════════════════════════════════════════════
// KLASSISCHER STIL (Java 8)
// ══════════════════════════════════════════════════
package com.example;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class BenutzerService {
public static void main(String[] args) {
List<Benutzer> benutzer = new ArrayList<>();
benutzer.add(new Benutzer("Max", "Müller", 30));
benutzer.add(new Benutzer("Anna", "Schmidt", 25));
// Stream API (Java 8)
List<String> namen = benutzer.stream()
.filter(b -> b.getAlter() > 20)
.map(b -> b.getVorname() + " " + b.getNachname())
.collect(Collectors.toList());
for (String name : namen) {
System.out.println(name);
}
}
}
class Benutzer {
private String vorname;
private String nachname;
private int alter;
public Benutzer(String vorname, String nachname, int alter) {
this.vorname = vorname;
this.nachname = nachname;
this.alter = alter;
}
public String getVorname() { return vorname; }
public String getNachname() { return nachname; }
public int getAlter() { return alter; }
@Override
public boolean equals(Object o) { /* 15 Zeilen Boilerplate */ }
@Override
public int hashCode() { /* Noch mehr Boilerplate */ }
@Override
public String toString() {
return "Benutzer{vorname='" + vorname + "', nachname='" + nachname
+ "', alter=" + alter + "}";
}
}
// ══════════════════════════════════════════════════
// MODERNER STIL (Java 21)
// ══════════════════════════════════════════════════
package com.example;
// Record statt Klasse (Java 16) — immutable, equals/hashCode/toString automatisch
record Benutzer(String vorname, String nachname, int alter) {}
class BenutzerService {
public static void main(String[] args) {
// List.of() statt new ArrayList<> (Java 9)
var benutzer = List.of( // var statt explizitem Typ (Java 10)
new Benutzer("Max", "Müller", 30),
new Benutzer("Anna", "Schmidt", 25)
);
// .toList() statt .collect(Collectors.toList()) (Java 16)
var namen = benutzer.stream()
.filter(b -> b.alter() > 20) // b.alter() statt b.getAlter()
.map(b -> b.vorname() + " " + b.nachname())
.toList();
namen.forEach(System.out::println);
}
}
The entire Benutzer class (38 lines) has been reduced to a single line. That is the most visible difference.
3.2 Feature Overview by Version
Java 9 (2017) — The Module System
// module-info.java — neues Konzept, nicht rückwärtskompatibel
module com.example.app {
requires java.net.http;
exports com.example.api;
}
// Fabrikmethoden für Collections (endlich!)
List<String> list = List.of("a", "b", "c"); // Unveränderlich!
Set<String> set = Set.of("a", "b", "c");
Map<String, Integer> map = Map.of("key", 1, "key2", 2);
// Private Methoden in Interfaces
interface Greeter {
default void greetAll(List<String> names) {
names.forEach(this::greet);
}
private void greet(String name) {
System.out.println("Hallo " + name);
}
}
The module system (Project Jigsaw) was the biggest structural change since Java 1.0. In practice, however, many projects do not actively use it — most applications still run on the unnamed module/classpath.
Java 10 (2018) — var
// Lokale Typinferenz — der Compiler erkennt den Typ automatisch
var benutzer = new Benutzer("Max", "Müller", 30); // statt Benutzer benutzer = ...
var liste = new ArrayList<String>(); // statt ArrayList<String> liste = ...
var stream = liste.stream(); // statt Stream<String> stream = ...
// WICHTIG: var ist KEIN dynamischer Typ wie in JavaScript!
// Der Typ wird zur Compile-Zeit festgelegt, nicht zur Laufzeit.
// var funktioniert NUR für lokale Variablen, nicht für Felder oder Parameter.
Java 11 (2018, LTS) — New HTTP Client, String Methods
// Eingebauter HTTP-Client (ersetzt das uralte HttpURLConnection)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.header("Content-Type", "application/json")
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
// Neue String-Methoden
" Hallo ".strip(); // "Hallo" (wie trim, aber Unicode-aware)
" ".isBlank(); // true
"Zeile1\nZeile2".lines(); // Stream<String>
"Ha".repeat(3); // "HaHaHa"
// var in Lambda-Parametern (für Annotationen nützlich)
list.stream()
.map((@NotNull var s) -> s.toUpperCase())
.toList();
Java 14 (2020) — Switch Expressions, Helpful NullPointerExceptions
// Switch als Expression (gibt einen Wert zurück!)
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case WEDNESDAY -> 9;
default -> {
String s = day.toString();
yield s.length(); // yield statt return in Blöcken
}
};
// Endlich hilfreiche NullPointerExceptions!
// Vorher: "NullPointerException" (wo genau?!)
// Jetzt: "Cannot invoke String.toLowerCase() because the return
// value of User.getName() is null"
Java 15 (2020) — Text Blocks
// Mehrzeilige Strings (kein "\\n" + Konkatenation mehr nötig)
String json = """
{
"name": "Max",
"alter": 30,
"stadt": "Berlin"
}
""";
String html = """
<html>
<body>
<p>Hallo Welt</p>
</body>
</html>
""";
// Sealed Classes (Preview in Java 15, stabil ab Java 17)
// Beschränken welche Klassen eine Klasse erweitern dürfen (siehe Java 17 für stabile Version)
sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double base, double height) implements Shape {}
Java 16 (2021) — Records, Pattern Matching for instanceof
// Records — immutable Datenklassen in einer Zeile
// Erzeugt automatisch: Konstruktor, Getter, equals(), hashCode(), toString()
record Point(int x, int y) {}
var p = new Point(3, 4);
p.x(); // 3 (Achtung: x() statt getX()!)
p.y(); // 4
// Records können auch Validierung haben:
record Alter(int wert) {
Alter { // "Compact Constructor"
if (wert < 0) throw new IllegalArgumentException("Alter darf nicht negativ sein");
}
}
// Pattern Matching for instanceof (kein Cast mehr nötig!)
// Vorher (Java 8):
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.length());
}
// Jetzt (Java 16+):
if (obj instanceof String s) {
System.out.println(s.length()); // s ist automatisch gecastet!
}
// Stream.toList() — kein Collectors.toList() mehr nötig
var namen = stream.map(String::toUpperCase).toList();
Java 17 (2021, LTS) — Sealed Classes
// Sealed Classes: Der Compiler kennt ALLE möglichen Subtypen
sealed interface Ergebnis permits Erfolg, Fehler {}
record Erfolg(String daten) implements Ergebnis {}
record Fehler(String nachricht) implements Ergebnis {}
// Zusammen mit Pattern Matching wird das sehr mächtig:
String verarbeite(Ergebnis e) {
return switch (e) {
case Erfolg(var daten) -> "OK: " + daten;
case Fehler(var nachricht) -> "Fehler: " + nachricht;
// Kein default nötig — Compiler weiß, dass alle Fälle abgedeckt sind!
};
}
Java 21 (2023, LTS) — Virtual Threads, Pattern Matching for switch ⭐
// ═══ VIRTUAL THREADS — die größte Neuerung seit Lambdas ═══
// Vorher: Ein OS-Thread pro Task (teuer, ~1MB Stack pro Thread)
// Jetzt: Millionen von Virtual Threads möglich
// Einen Virtual Thread starten:
Thread.startVirtualThread(() -> {
System.out.println("Läuft auf einem virtuellen Thread!");
});
// Mit Executor:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 1_000_000; i++) {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return "Fertig";
});
}
}
// 1 Million gleichzeitige Tasks — mit klassischen Threads unmöglich!
// In Spring Boot 3.2+ reicht eine Zeile in application.properties:
// spring.threads.virtual.enabled=true
// → Alle Requests laufen automatisch auf Virtual Threads
// ═══ PATTERN MATCHING FOR SWITCH — voll ausgereift ═══
String formatiere(Object obj) {
return switch (obj) {
case Integer i when i > 0 -> "Positive Zahl: " + i;
case Integer i -> "Negative oder Null: " + i;
case String s -> "Text: " + s;
case null -> "null!";
default -> "Unbekannt: " + obj;
};
}
// ═══ RECORD PATTERNS — Destrukturierung ═══
record Point(int x, int y) {}
// Direkt in Pattern Matching destrukturieren:
if (obj instanceof Point(int x, int y)) {
System.out.println("x=" + x + ", y=" + y);
}
// ═══ SEQUENCED COLLECTIONS — endlich einheitlicher Zugriff ═══
SequencedCollection<String> list = new ArrayList<>(List.of("A", "B", "C"));
list.getFirst(); // "A"
list.getLast(); // "C"
list.reversed(); // ["C", "B", "A"]
// ═══ UNNAMED VARIABLES — Unterstrich für ungenutzte Variablen ═══
try {
int i = Integer.parseInt(input);
} catch (NumberFormatException _) { // _ statt "e" wenn nicht verwendet
System.out.println("Ungültige Zahl");
}
Virtual threads are particularly relevant for highly parallel server applications: Spring Boot on Java 21 with virtual threads can serve hundreds of thousands of concurrent HTTP requests with minimal resource consumption — similar to Go's goroutines, but in Java.
4. GUI Libraries: Swing Is Dead, Long Live JavaFX
4.1 Current Status
| Framework | Status | Recommendation |
|---|---|---|
| AWT | Ancient, feature-frozen | Do not use |
| Swing | Feature-frozen, only bug fixes | Only for legacy maintenance. IntelliJ IDEA is still based on it |
| JavaFX (OpenJFX) | Actively maintained, 2 releases/year | ⭐ Standard for new desktop apps |
| SWT | Eclipse-based, future uncertain | Wait and see |
| Compose Desktop | JetBrains (Kotlin-based) | Modern, declarative — like Flutter for Java/Kotlin |
| Vaadin | Web framework, server-side | Java-only alternative to JS frontends |
4.2 What Happened to JavaFX?
Since Java 11, JavaFX is no longer part of the JDK. It was spun off as a standalone open-source project (OpenJFX) and is actively developed by the community and Gluon. This means:
- JavaFX is included as a Maven/Gradle dependency, instead of being "just there"
- JavaFX has its own versioning (currently version 23/24)
- Only exception: BellSoft Liberica JDK still includes JavaFX built-in
<!-- JavaFX als Maven-Dependency einbinden -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>21.0.2</version>
</dependency>
4.3 Desktop Applications in Java Today
Desktop development with Java is significantly less common than in earlier years. Most applications are web-based today. The main exceptions are IDEs (IntelliJ, Eclipse, NetBeans) and specialised enterprise software.
For new desktop apps in the JVM world, Compose Desktop (Kotlin, by JetBrains) is the most modern approach — declarative UI similar to Svelte or React, but in Kotlin.
5. Build Tools: Maven Lives On, Gradle Is Catching Up
5.1 Maven Today
Maven still exists and remains the most widely used build tool in the Java world. The basic structure (pom.xml, lifecycle, repositories) has barely changed since the Java 8 era. If you knew Maven 3 then, you still know it today.
Recent developments:
- Maven 4 is in development (for years now) and aims to modernise the POM format
- Maven Wrapper (
mvnw) — similar to Gradle Wrapper: the Maven version is bundled with the project, so every developer uses exactly the same version - Maven Daemon (
mvnd) — keeps a JVM running for faster builds (inspired by Gradle)
# Maven Wrapper generieren (mit dem Maven Wrapper Plugin)
mvn wrapper:wrapper
# Dann statt "mvn" einfach:
./mvnw clean install
5.2 Gradle as an Alternative
Gradle is the challenger that has gained massive adoption primarily through Android development (Google chose Gradle as the standard build tool for Android).
| Aspect | Maven | Gradle |
|---|---|---|
| Configuration language | XML (pom.xml) |
Groovy or Kotlin DSL (build.gradle.kts) |
| Philosophy | Convention over Configuration (rigid) | Flexible, programmable |
| Performance | Good, but no caching | Incremental builds, build cache, daemon — 2-5x faster |
| Adoption (2025) | ~52% of Java projects | ~48% of Java projects |
| Learning curve | Easier, because more rigid | Steeper, because more flexible |
| Plugin ecosystem | Huge, more plugins available | Large, but slightly smaller |
| IDE integration | Excellent in all IDEs | Very good, excellent in IntelliJ |
// build.gradle.kts (Kotlin DSL) — zum Vergleich mit pom.xml
plugins {
java
id("org.springframework.boot") version "3.2.0"
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.postgresql:postgresql:42.7.1")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
5.3 Recommendation
If you already have Maven experience, it is worth sticking with it. It works, you know it, and for a Spring Boot project it makes no practical difference. Gradle is mainly worthwhile for very large multi-module projects or for Android development.
6. The Ecosystem: Frameworks and Libraries
6.1 Web Frameworks
| Framework | Description | Status 2025 |
|---|---|---|
| Spring Boot | The dominant Java web framework | ⭐ De facto standard. Version 3.x requires Java 17+ |
| Jakarta EE (formerly Java EE) | Enterprise standard | Still alive, was handed from Oracle to the Eclipse Foundation. "javax." → "jakarta." |
| Quarkus | "Supersonic Subatomic Java" from Red Hat | Rising. Optimised for cloud/containers, GraalVM native images |
| Micronaut | Compile-time DI, no reflection | Rising. Competitor to Quarkus |
| Vert.x | Reactive, event-driven framework | Niche, but high-performance |
6.2 Jakarta EE: The Name Change
Java EE was handed from Oracle to the Eclipse Foundation and is now called Jakarta EE. The most important practical consequence: all package names have changed.
// Vorher (Java EE):
import javax.servlet.http.HttpServlet;
import javax.persistence.Entity;
// Jetzt (Jakarta EE):
import jakarta.servlet.http.HttpServlet;
import jakarta.persistence.Entity;
This also affects JPA/Hibernate, Servlets, JAX-RS, CDI, etc. Spring Boot 3.x requires Jakarta EE — so upgrading from Spring Boot 2.x to 3.x also means this namespace change.
6.3 JVM Languages
The JVM today is not just for Java. Several languages run on the same VM:
| Language | Use Case |
|---|---|
| Kotlin | Android (officially recommended by Google), server-side (Spring supports Kotlin first-class), multi-platform |
| Scala | Big Data (Apache Spark), functional programming |
| Groovy | Gradle build scripts, Jenkins pipelines, scripting |
| Clojure | Functional programming (Lisp on the JVM) |
Kotlin is the most significant development here: it is essentially a "better Java" with null safety, coroutines, extension functions, and significantly less boilerplate. Many Spring Boot projects are now written in Kotlin instead of Java.
6.4 Important Libraries (What Has Changed)
| Area | Then (Java 8) | Today |
|---|---|---|
| JSON | Jackson, Gson, manually included | Jackson (built into Spring Boot), Gson still popular |
| HTTP client | Apache HttpClient, HttpURLConnection | java.net.http.HttpClient (built-in since Java 11!) |
| Logging | Log4j, SLF4J + Logback | SLF4J + Logback (default in Spring Boot). Log4j 1 is EOL, Log4j2 had a critical security vulnerability in 2021 |
| Testing | JUnit 4 | JUnit 5 (completely new, modular architecture, @Test from org.junit.jupiter) |
| ORM | Hibernate 4/5 | Hibernate 6 (with Jakarta EE namespace), Spring Data JPA abstracts much of it |
| Reactive | Non-existent | Project Reactor (Spring WebFlux), RxJava |
| Dependency Injection | Spring Framework, CDI | Spring Boot (auto-configuration), Quarkus/Micronaut (compile-time DI) |
| Database migration | Manual or Liquibase | Flyway (most popular) or Liquibase |
7. Garbage Collectors: New Generation
The JVM today has several highly optimised garbage collectors:
| GC | Since | Characteristic |
|---|---|---|
| G1 | Java 9 (default) | Balanced, good all-rounder — active by default |
| ZGC | Java 15 (stable), Java 21 (generational) | Ultra-low pause times (<1ms), even with huge heaps |
| Shenandoah | Java 15 (stable) | Similar to ZGC, developed by Red Hat |
The CMS (Concurrent Mark Sweep) and the Parallel GC from earlier Java versions have been replaced by G1. ZGC and Shenandoah are the future for latency-sensitive applications.
8. GraalVM and Native Images
One of the most exciting developments: GraalVM can compile Java applications into native binaries (ahead-of-time compilation). The result starts in milliseconds instead of seconds and uses significantly less memory.
# Native Image bauen (mit Spring Boot 3 + GraalVM)
./mvnw -Pnative native:compile
# Ergebnis: Eine eigenständige Binary (~50-80 MB)
./target/mein-service # Startet in ~50ms statt 2-3 Sekunden
Frameworks like Quarkus and Micronaut are explicitly optimised for this. Spring Boot has supported native images since version 3.0, but with limitations (reflection-based features do not work without configuration).
9. IDEs for Java Today
| IDE | Status | Cost |
|---|---|---|
| IntelliJ IDEA Community | ⭐ Most popular Java IDE | Free (open source) |
| IntelliJ IDEA Ultimate | Full version with web/DB/framework support | Paid (EUR 599/year, or ~EUR 199/year for individuals) |
| Eclipse | Still active, but declining | Free |
| NetBeans | Now an Apache project, less widespread | Free |
| VS Code + Java Extensions | Works, but not IDE-level | Free |
The IntelliJ IDEA Community Edition is perfectly sufficient for most Java projects. Those who use Spring Boot intensively benefit from the Ultimate Edition (Spring support, database tools, HTTP client). There is a 30-day trial version.
10. Summary: What Has Changed
The Top 10 Changes Since Java 8
- Records (Java 16) — Immutable data classes in a single line
- var (Java 10) — Local type inference
- Text Blocks (Java 15) — Multi-line strings with
""" - Pattern Matching (Java 16/21) — instanceof without cast, switch with types
- Sealed Classes (Java 17) — Restricted inheritance
- Switch Expressions (Java 14) — Switch returns values
- Virtual Threads (Java 21) — Millions of lightweight threads
- Module System (Java 9) — Exists, but often ignored
- New Collection Methods —
List.of(),.toList(),getFirst()/getLast() - HTTP Client (Java 11) — Finally a modern built-in HTTP client
What Has NOT Changed
- Java is still statically typed and object-oriented
- The JVM is still the JVM (HotSpot)
- Maven
pom.xmlstill looks the same - Classes, interfaces, inheritance, generics — all unchanged
public static void main(String[] args)still works- The ecosystem is massive and backward-compatible
The Short Version
Recommended distribution: Eclipse Temurin Java 21 (via SDKMAN)
Build tool: Maven (proven) or Gradle (for large projects)
Framework: Spring Boot 3.x
IDE: IntelliJ IDEA Community (or Ultimate for Spring support)
GUI: JavaFX (if desktop is needed)
Testing: JUnit 5
Appendix: Learning Resources
- "New language features since Java 8 to 21" — Compact overview with code examples https://advancedweb.hu/new-language-features-since-java-8-to-21/
- WhichJDK.com — Which JDK distribution should I choose? https://whichjdk.com/
- Baeldung — The most comprehensive Java tutorial portal https://www.baeldung.com
- Spring Boot Guides — Official getting-started guides https://spring.io/guides
- JDK Comparison — Detailed comparison of all JDK distributions https://jdkcomparison.com/
- SDKMAN — Java version manager for Linux/macOS https://sdkman.io
Comments
Comments are provided by Remark42. By loading comments, data is transmitted to our comment server.