Ist Java Cloud-nativ?

Dmitry Chuyko

2025 feiert Java sein 30-jähriges Bestehen und erfreut sich nach wie vor großer Beliebtheit. Dank der hervorragenden Abwärtskompatibilität, der engagierten Community sowie der Vielzahl an Tools und Lösungen zur Erleichterung der Entwicklung mit Java bleibt die Plattform die bevorzugte Wahl für Unternehmensanwendungen.

Wenn es allerdings um Cloud-native Programmiersprachen geht, zeichnen sich Go, JavaScript, Ruby, Kotlin oder Rust durch ihre besonders hohe Geschwindigkeit und Effizienz sowie Benutzerfreundlichkeit aus – Eigenschaften, die sie zur bevorzugten Wahl für neue Projekte machen. Auch WebAssembly (Wasm) wird bei der Webentwicklung immer beliebter. Die Fähigkeit von Java zur Erstellung Cloud-nativer Programme wird allerdings oft mit Vorsicht genossen.

Es stellt sich also folgende Frage: Ist Java Cloud-nativ? Die Antwort mag für alle, die die Entwicklung der Plattform nicht im Detail verfolgt haben, nicht sofort ersichtlich sein. Immerhin hat Java einen langen Weg zurückgelegt, bis es sich als fester Bestandteil der Cloud-Welt etablieren konnte. In diesem Artikel werden die bedeutendsten Meilensteine auf Javas Reise in die Cloud näher beleuchtet.

Was bedeutet „Cloud-nativ“?

Bevor wir darauf eingehen, inwiefern Java Cloud-nativ ist, sollten wir uns mit dem Begriff der Cloud-Nativität auseinandersetzen. 

„Cloud-nativ“ bezeichnet einen Ansatz zur Entwicklung, Bereitstellung und Ausführung von Anwendungen in einer Cloud-Umgebung, der hohe Flexibilität, Skalierbarkeit und Verfügbarkeit ermöglicht. Cloud-native Anwendungen können überaus schnell skaliert werden, um mit dem eingehenden Traffic Schritt zu halten, und lassen sich ständig anpassen, ohne die Verfügbarkeit der Anwendung für Nutzer einzuschränken.

Google definiert beispielsweise vier Säulen, die eine Cloud-native Anwendung auszeichnen: Microservices, Container, DevOps, Continuous Integration/Continuous Delivery (CI/CD). Diese können wie folgt beschrieben werden:

  • Microservices sind kleine, gekoppelte Services, die jeweils eine spezifische Aufgabe übernehmen und unabhängig von anderen Services geändert werden können. Sie kommunizieren über APIs (Application Programm Interfaces) und steigern die Flexibilität und Zuverlässigkeit Cloud-nativer Anwendungen. APIs fungieren hierbei als Brücke zwischen den Services und ermöglichen so den Informationsaustausch – sogar zwischen Services, die in unterschiedlichen Programmiersprachen entwickelt wurden. 
  • Container sind Softwarepakete, die alles enthalten, was eine Anwendung benötigt, um in der Cloud zu laufen: den Anwendungsquellcode, Abhängigkeiten, Bibliotheken, Framework, Betriebssystem und Laufzeitumgebung.
  • Continuous Integration/Continuous Delivery oder schlicht CI/CD umfasst eine Reihe von Praktiken, die darauf abzielen, die Entwicklung, Testung und Bereitstellung von Software zu optimieren. CI/CD setzt auf einen hohen Automatisierungsgrad und ermöglicht die schnellere Entwicklung und den schnelleren Release qualitativ hochwertiger Software.
  • DevOps ist eine Bereitstellungsmethodologie, die eine engere Zusammenarbeit zwischen Entwicklungs- und IT-Operations-Teams ermöglicht. So werden die Release-Zyklen und Time-to-Market verkürzt und den Nutzern qualitativ hochwertige Software geliefert, die ihren Erwartungen entspricht. 

Eine effiziente Cloud-native Infrastruktur muss allerdings darüber hinaus über zwei weitere unverzichtbare Bestandteile verfügen:

  • Die Container-Orchestrierung lässt Sie die Bereitstellung und Skalierung von Containern je nach Workload-Anforderungen automatisieren. Die beliebteste Plattform für Container-Orchestrierung, Kubernetes, bietet fertige Lösungen für die effiziente Verwaltung containerisierter Workloads in der Cloud. 
  • Observability ermöglicht es, die internen Zustände verteilter Systeme in der Cloud zu messen, wobei Daten in Form von Metriken oder Traces gesammelt werden. Bei Cloud-nativen Workloads ist Observability von entscheidender Bedeutung, da sie dabei hilft, komplexe Systeme zu navigieren und Probleme schnell zu identifizieren.

Was sind die Hauptherausforderungen einer Cloud-Umgebung?

  • Die Verwaltung verteilter Systeme. Cloud-native Microservices bilden oftmals komplexe Systeme mit anspruchsvollen Interaktionen, die schwieriger zu testen, zu debuggen und zu aktualisieren sind als eine traditionell monolithische Architektur. Umso wichtiger ist es, dass das Ökosystem rund um die gewählte Plattform alle notwendigen Tools zur Entwicklung und Wartung solcher Systeme umfasst.
  • Erhöhte Betriebs- und Technologiekosten durch fehlende Kostenoptimierung. Ein Mangel an Kontrolle über die Ressourcennutzung in der Cloud kann zu einer suboptimalen Auslastung führen und somit die Cloud-Kosten in die Höhe treiben.
  • Reibungsloser, schneller und weitgehend automatisierter Workflow von der Entwicklerumgebung bis zur Produktion. Hierbei ist entscheidend, dass das Ökosystem rund um die Programmiersprache Bausteine bietet, die eine solche Pipeline ermöglichen.
  • Mangel an technischer Expertise bei komplexen Technologie-Stacks. Die Arbeit mit Cloud-Infrastrukturen erfordert Erfahrung mit verschiedenen neuen Technologien. Es wäre daher von Vorteil, wenn möglichst viele Entwickler mit einem breiten Spektrum an Fähigkeiten und Erfahrungswerten im Hinblick auf die Programmiersprache gegeben sind.
  • Vorbehalte gegen den Kulturwandel, der für die Implementierung von Cloud-nativen Technologien und DevOps-Best-Practices erforderlich ist.
  • Schwierigkeiten bei der Vermittlung Cloud-nativer Konzepte an technisch nicht versierte Entscheidungsträger zur Gewinnung von Unterstützung und Zustimmung.

Zusammenfassend lässt sich festhalten, dass Cloud-native Anwendungen unter Verwendung Cloud-nativer Tools entwickelt und erstellt werden und einige oder alle der folgenden Merkmale aufweisen: Sie sind in Microservices unterteilt, containerisiert, in eine CI/CD-Pipeline eingebettet, nach DevOps-Best-Practices entwickelt und können sowohl horizontal als auch vertikal skaliert werden. Der Schlüssel liegt darin, Services schnell zu entwickeln, bereitzustellen und auszuführen, ohne dabei unnötige Cloud-Ressourcen zu verbrauchen. 

Wie also passt Java in dieses Paradigma?

Wie Java zur Cloud aufstieg

Java hat seit mittlerweile über drei Jahrzehnte hinweg seinen Platz als eine der beliebtesten Programmiersprachen für Unternehmensanwendungen behaupten können. Das Geheimnis seines Erfolgs liegt in den kontinuierlichen Anstrengungen der Plattformentwickler, Java an die Nutzeranforderungen und -bedürfnisse anzupassen. Das Java von heute lässt sich nicht mehr mit dem Java vor 29 Jahren vergleichen. Um also die Frage zu beantworten, ob Java als Cloud-nativ betrachtet werden kann, sollten wir zunächst die Meilensteine seiner Reise in die Cloud betrachten.

Die Implementierung cloud-freundlicher Funktionen erfolgte bei Java Schritt für Schritt. Obwohl das Ziel der Plattformentwickler nicht ausschließlich darin bestand, Java Cloud-Nativität zu verleihen, wurde dieser Aspekt doch zunehmend relevanter, je populärer Cloud-Bereitstellungen wurden.

Angesichts der bereits geschilderten Herausforderungen war Java zunächst kein idealer Kandidat für die Cloud, auch wenn es von Anfang an mit einigen herausragenden Eigenschaften aufwartete: automatische Speicherbereinigung, hohe Performance, Build-Systeme und Plattformunabhängigkeit. Die Unterstützung von Containern sollte noch ausgebaut werden.

JDK 9 enthielt einige Verbesserungen, darunter kompakte Strings zur Optimierung des Speicherverbrauchs von JVM, eine neue HTTP-Client-API, die HTTP/2 und WebSocket implementiert, sowie die Unterstützung von cgroups-Speicherbegrenzungen in Containern. Darüber hinaus war es ab JDK 9 möglich, benutzerdefinierte Laufzeit-Images zu erstellen, dank denen die Größe von Docker-Container-Images reduziert werden kann.

JDK 10 brachte eine verbesserte Docker-Container-Identifizierung und Ressourcenkonfiguration. Zudem wurden neue JVM-Flags eingeführt, mit denen der Prozentsatz des für die JVM verfügbaren Arbeitsspeichers manuell angepasst werden konnte.

JDK 11 führte eine interne API zur Extraktion container-spezifischer Konfigurationen und Laufzeitstatistiken ein, was die Observability von containerisierten Java-Workloads verbesserte.

Auch die Algorithmen von Javas Garbage Collector wurden weiter optimiert, um den Anforderungen einer Cloud-Umgebung gerecht werden zu können. JDK 11 beinhaltete den neuen Low-Pause ZGC (Z-Garbage Collector), JDK 12 den Low-Pause Shenandoah GC, die beide mit JDK 15 einsatzbereit wurden. Ebenfalls ab JDK 12 verfügbar war der G1 GC (Garbage-First Garbage Collector), der ungenutzten Heap-Speicher in das Betriebssystem zurückführt. Die Garbage Collectors werden fortlaufend weiterentwickelt, was sich beispielsweise am ZGC zeigt, der mit JDK 21 einen Generationsmodus erhielt, um den CPU-Speicher-Overhead zu verringern. Der Shenandoah GC soll mit JDK 24 ebenfalls einen Generationsmodus erhalten. Zudem erhält der G1 GC in JDK 24 zur Reduzierung von JVM-Overhead bei der Kompilierung eine Late Barrier Expansion.

Entscheidend war also die Optimierung des Ressourcenverbrauchs in Containern sowie die Reduzierung der Java-Container-Images. Ab einem bestimmten Zeitpunkt wurde das minimalistische Alpine Linux zum neuen Standard in der Cloud-nativen Entwicklungswelt, das mit einem Basis-Image von nur etwa drei Megabyte und der Unterstützung von musl libc die Erstellung schlanker Container-Images ermöglichte. Java zog mit der Unterstützung für Alpine Linux in JDK 16 nach, womit kleine Container-Images auch mit Java-Programmen möglich wurden.

Darüber hinaus lieferte JDK 16 eine verbesserte Metaspace-Elastizität, die in bestimmten Fällen exzessivem Speicherverbrauch entgegenwirken und so die Kosten containerisierter Workloads verringern kann.

Dies sind nur die wesentlichen Verbesserungen – eine Auflistung aller Optimierungen und Fehlerbehebungen, die Javas Effizienz in der Cloud gesteigert hat, würden den Rahmen dieses Artikels sprengen. Zusammenfassend lässt sich sagen, dass Javas Aufstieg in die Cloud ein Erfolg war. Doch eine solche Reise findet nie ein Ende: Neue Herausforderungen erfordern neue Lösungsansätze, weshalb Java weiterhin stetig verbessert wird.

Neue Herausforderungen, neue Lösungen

Das Ausführen Cloud-nativer Workloads birgt nicht nur enorme Chancen, sondern auch spezifische Herausforderungen. Mit schlecht durchdachten Cloud-Deployment-Strategien und unzureichend gestalteten Cloud-Infrastrukturen riskieren Unternehmen, SLAs zu verletzen und/oder unerwartet hohe Cloud-Kosten tragen zu müssen.

Ein wesentlicher Faktor zur Optimierung der Cloud-Kosten ist die Fähigkeit, Ressourcen je nach Traffic zu skalieren, da Cloud-Infrastrukturen Services mit unterschiedlichen Loads oder schwankenden Traffic-Spitzen umfassen können. Es wäre folglich kosteneffizienter, nur für Ressourcen zu zahlen, wenn der Service tatsächlich genutzt wird. Hier bieten sich Lösungen wie beispielsweise AWS Lambdas oder Google Functions, die den Service nur bei eingehendem Traffic aktivieren, sowie Funktionen zur automatischen Skalierung oder Function-as-a-Service (FaaS), bei denen Code als Reaktion auf bestimmte Ereignisse erstellt und ausgeführt wird.

Bei der Cloud dreht sich also alles um Geschwindigkeit, Effizienz und Automatisierung. Ein perfekter Service lässt sich einfach schreiben, konfigurieren, containerisieren und bereitstellen. Er verbraucht keine unnötigen Cloud-Ressourcen, startet schnell und lässt sich bequem der Nachfrage entsprechend skalieren.

Erstaunliche Tatsache: Das alles ist mit Java möglich! Die Einrichtung einer Cloud-nativen Java-Umgebung ist einfach. Alles, was Sie dazu benötigen, ist:

  • eine Java-Anwendung;
  • Docker zur Erstellung und Veröffentlichung von Container-Images;
  • Kubernetes für die Orchestrierung von Containern;
  • ein Ingress-Controller wie NGINX für den Zugriff auf Kubernetes und der Bereitstellung von Diensten für Nutzer;
  • ein Framework wie beispielsweise Spring Boot und
  • Apache Maven oder Gradle.

Die Geheimzutat besteht aus Cloud-nativen Buildpacks. Buildpacks verwandeln den Quellcode einer Anwendung in ausführbare Artefakte mit minimaler Konfiguration. Sie stellen eine perfekte Lösung für die Cloud dar, da mit ihnen keine Notwendigkeit besteht zur Entwicklung und Wartung der Build-Umgebung besteht, was wiederum Automatisierung und Standardisierung steigert. 

Da Container Isolation bieten, benötigen Sie für die Nutzung von Buildpacks lediglich Docker und einige wenige Tools, um den Build-Prozess zu starten, wie beispielsweise das pack CLI für Buildpacks von Paketo. Darüber hinaus unterstützen Spring und andere gängige Java-Frameworks die Containerisierung mit Buildpacks über Maven- und Gradle-Plugin.

Und noch besser: Buildpacks sind leicht zu konfigurieren. Ihr Modus Operandi basiert auf sogenannten Stacks, wobei es einen Build-Stack und einen Run-Stack gibt, die Basis-Images gruppieren, welche wiederum für die Entwicklung und Ausführung einer Anwendung erforderlich sind. Ein Build-Stack für Java enthält beispielsweise JDK, während ein Run-Stack JRE umfasst. Die Stacks werden automatisch gewählt, sodass Sie keine Gedanken an den Prozess verschwenden müssen. Sie können die Stacks allerdings auch den Anforderungen ihres Projekts anpassen.

Sie können entweder das Standard-JDK verwenden oder von Build-Paketen mit einem schlanken JDK profitieren – oder sogar mit dem jlink-Tool eine benutzerdefinierte Laufzeit für Ihre Anwendung erstellen. Javas Weg in die Produktion war nie schneller! 

Um das Problem langer Java-Start- und Warmup-Zeiten zu lösen, können Sie GraalVM Native Image nutzen, das Java-Anwendungen in vollständig kompilierte, plattformspezifische native Executables umwandelt, die nahezu ohne Zeitverzögerung starten und Spitzen-Performance bieten. Es ist tatsächlich sogar möglich, vollständig statische native Images zu erstellen, die auf Distroless-Images laufen – ein weiterer Trend in der Cloud-Welt. 

Der Grund, weshalb GraalVM Native Image nicht in der Liste aufgeführt wird, liegt darin, dass das Tool nicht separat installiert werden muss. Die Erstellung von nativen Images kann auch über Buildpacks erfolgen! Falls Sie native Images für verschiedene Plattformen erstellen möchten, gibt es dafür eine GitHub Action.

So werden Java-Anwendungen mit einem einzigen Befehl in native Images umgewandelt und containerisiert, bevor sie in der Pipeline weiterverarbeitet werden. In der Produktion können diese Images mühelos skaliert werden, was die Cloud-Kosten optimiert.

Die Java-Programmiersprache ist weiterhin ausdrucksstärker geworden. Java-Programme sind dank neuer Funktionen wie Pattern Matching für switch-Anweisungen und -Ausdrücke schlanker und prägnanter geworden, und sie kommunizieren dank der Foreign Function & Memory API sowie anderen Tools zuverlässiger mit anderen Sprachen.

KI spielt eine zentrale Rolle in modernen Cloud-nativen Setups, weshalb Lösungen des Java-Ökosystems wie Spring AI die Integration von Sprachmodellen und KI-Chatbots in Java-Programme ermöglichen.  

Das ist aber noch nicht alles: Java-Anwendungen laufen dank Virtueller Threads seit JDK 21 noch effizienter, welche dabei helfen, Java-Anwendungen zu skalieren und gleichzeitig eine optimale Hardware-Auslastung zu erzielen. Darüber hinaus wurde Javas Familie der Garbage Collectors um zwei Low-Pause Collectors, ZGC und Shenandoah GC, erweitert, die beide mit JDK 15 einsatzbereit wurden. Sie eignen sich für besonders große Heaps im Terabyte-Bereich und/oder latenzempfindliche Anwendungen. 

Alles in allem befinden sich die Entwickler der Java-Plattform also stets am Puls der Zeit mit allen neuesten Trends und modernen Anforderungen in der Softwareentwicklung. Da die Cloud mittlerweile ein unverzichtbarer Bestandteil der meisten Softwareprojekte ist, arbeitet das Team kontinuierlich an der Einführung und Optimierung von Funktionen, die Java-Services schneller, schlanker und effizienter in der Cloud-Umgebung machen.

Deshalb ist Java die optimale Wahl bei Cloud-nativen Workloads

Unter Berücksichtigung aller besprochenen Punkte besteht kein Zweifel daran, dass Java – mittlerweile – Cloud-nativ ist. Jahre der Entwicklung haben Java zu einer erstklassigen Wahl für die Entwicklung und den Betrieb Cloud-nativer Anwendungen gemacht, was der vielseitigen Effizienz Javas zu verdanken ist:

  • Proaktive Community aus Entwicklern und Unternehmen, die kontinuierlich zur Verbesserung der Plattform beitragen;
  • effizienter Entwicklungsfortschritt durch einen strikten Release-Plan und zweijährliche Releases mit langfristigem Support;
  • kleine, sichere und schnelle Container-Images;
  • exzellente Spitzen-Performance und Unterstützung moderner Hardware;
  • vielfältige Lösungen zur schnellen Erreichung von Spitzenperformance.

Fazit

In diesem Artikel haben wir Javas Weg in die Cloud nachverfolgt, seine Eigenschaften erörtert und dargelegt, welche Faktoren Java zur richtigen Wahl für Cloud-native Unternehmensanwendungen machen. 

Java ist die ideale Lösung für die Cloud, wobei es zahlreiche Funktionen, Tools und Lösungen gibt, die für einen reibungslosen Ablauf bei der Entwicklung und Ausführung von Cloud-nativen Anwendungen sorgen. Dank der aktiven OpenJDK-Community sowie der Beiträge einzelner Entwickler und Unternehmen zur Verbesserung der Plattform steht sicher fest, dass Java sich weiterhin entwickeln und seinen Platz unter den beliebtesten Programmiersprachen auch in den kommenden Jahren beibehalten wird.

Neugierig, was Java sonst noch kann?
In diesem Artikel beleuchtet Dmitry Chuyko Java als cloud-native Plattform.
Auf der JCON zeigt er in „Legal JVM Doping“, wie sich mit Tools wie CRaC, Leyden & GraalVM die Performance pushen lässt – ganz ohne Codeänderung.
Das Session-Video ist nach der Konferenz verfügbar – anschauen lohnt sich!

Total
0
Shares
Previous Post

Eclipse Data Grid: Die Java-Native In-Memory-Datenplattform

Next Post

JAVAPRO Magazin – Java 25 Special Edition – Call for Papers

Related Posts