• Zuhause
  • Artikel
  • OpenJDK 9 und 10 - Wichtige Funktionen für Cloud-Umgebungen
Veröffentlicht am 28-02-2019

OpenJDK 9 und 10 - Wichtige Funktionen für Cloud-Umgebungen

In diesem Artikel erfahren Sie mehr über JDK 9 und JDK 10 von Luigi Fugaro, einem Architekten des EMEA Middleware-Teams, der alle Arten von Webanwendungen entwickelt hat, die sich mit Backend- und Frontend-Frameworks beschäftigen.

Foto von Nicholas Swanson auf Unsplash

Die neue Ära der Informationstechnologie hat eine konstante, aber schrittweise Entwicklung von Sprachen, Rahmenbedingungen und Architekturen durchlaufen. Der große Wettbewerb, der den globalen Markt antreibt, hat zur Notwendigkeit einer umfassenden Überprüfung der Entwicklungsplattformen und ihrer Aktualisierungs- und Entwicklungsprozesse geführt.

Java

Aus Sicht der Anwendungsentwicklung hat Open Sourcing über die Jahre einen großen Beitrag geleistet. Eine der beliebtesten Programmiersprachen, die dank der Hilfe von Open Source Communities gewachsen ist, ist Java.

Java, das von Sun Microsystems veröffentlicht wurde, wurde mit dem Konzept erstellt, dass das Schreiben einmal ausgeführt wird. Das Versprechen einer großen Portierbarkeit von Software, eines einfachen Lernens und der Verwendung seitens der Entwickler hat die schnelle Verbreitung von Java im Informationstechnologie-Ökosystem ermöglicht.

Die Arbeit, die Sun in diesen zehn Jahren von der ersten öffentlichen Veröffentlichung von 1996 bis zur Gründung von OpenJDK und der Open-Source-Veröffentlichung der JVM-Kern- und JSE-Plattform im Jahr 2007 leistete, ließ seine Rolle in Bezug auf Java idealerweise wie die eines Evangelisten erscheinen .

Java hat sich seitdem durch verschiedene Stakeholder wie Oracle Corporation und Eclipse Foundation entwickelt. Java SE 9 und 10 sind die neuesten OpenJDK-Versionen mit vielversprechenden Funktionen und Verbesserungen.

In diesem Artikel werden wir einige der wichtigsten Neuerungen in JDK 9 und 10 betrachten, die den Einsatz von Java in Cloud-Plattformen und Microservices verbessert haben.

JDK 9

Java SE 9 ist das revolutionäre Element, das die durch das Jigsaw-Projekt erreichte Modularisierung des JDK mit sich bringt.

Das Hauptziel von JDK 9 bestand darin, Java SE flexibler und skalierbarer zu machen, die Sicherheit und Wartung zu verbessern, das Erstellen, Verwalten, Bereitstellen und Aktualisieren großer Anwendungen zu vereinfachen und die Leistung zu verbessern.

Kritikpunkte

Zuvor hatte die Community zwei Hauptkritikpunkte an der Java SE-Plattform:

· Die Langsamkeit in der Veröffentlichung der neueren Versionen

· Die Größe des JDK in Bezug auf die Belegung und die Klassengröße (ca. 4.240 Klassen in JDK 8)

Lösung

Es war schwierig, eine Lösung zu finden, die es erlaubt, diese Grenzen zu überwinden, ohne die Abwärtskompatibilität zwischen den Versionen aufzugeben.

Daher wurde es schwierig, veraltete Klassen oder Klassen, die für den internen Gebrauch entwickelt wurden, zu beseitigen, aber insbesondere durch das Framework intensiv über Java-Reflektion verwendet werden.

Durch das Jigsaw-Projekt wurde es möglich, das JDK im Kerncode zu modularisieren und ein Werkzeug für die Realisierung von Anwendungen bereitzustellen, mit dem die Schnittstellen der Exposition seiner Dienste hinsichtlich der tatsächlichen Implementierung erheblich entkoppelt werden können.

Für JDK-Kerncode ist es möglich, JDK-APIs wie in JEP 260 beschrieben mit dem folgenden Ansatz zu kapseln:

  • Standardmäßig kapseln Sie alle internen APIs, die als nicht kritisch gelten
  • Kapselung aller internen APIs, die als kritisch gelten, für die in JDK 8 unterstützte Ersetzungen vorhanden sind
  • Schließen Sie keine kritischen internen APIs ein, sondern implementieren Sie die folgenden Schritte:
  • Verurteilen Sie sie in JDK 9
  • Definieren Sie einen Plan zum Entfernen dieser APIs in JDK 10
  • Implementieren Sie eine Problemumgehungslösung über einen Befehlszeilenparameter
  • Entfernen Sie aus der JDK-Distribution eine begrenzte Anzahl unterstützter JCP-Standard-APIs (Java Community Process)
  • Entfernen Sie die Erweiterungsmechanismen und die genehmigte Standardeinstellung
  • Java EE-Module werden aufgrund des Projekts Jigsaw standardmäßig nicht aufgelöst

Auf diese Weise können Sie leicht eine kleine bootfähige Java-Laufzeitumgebung erhalten, die nur die Funktionen enthält, und zwar in Bezug auf Klassen und Schnittstellen, die Sie wirklich benötigen. Dies vermeidet das Vorhandensein von nutzlosem Code, der nur negative Nebeneffekte hinsichtlich der Footprint- und Speicherplatzzuordnung haben kann.

Sie können dies beispielsweise mit dem folgenden Befehl leicht analysieren:

$ java -listmods

Wie bereits erwähnt, können sowohl das JDK als auch die Anwendung von der modularen Entwicklung profitieren.

Modul

Die Entkopplung der in den Anwendungen vorhandenen Komponenten ist für Microservice-Architekturen unerlässlich, die einen sehr agilen Software-Lebenszyklus benötigen, um die Markteinführungszeit zu verkürzen. Mit einem modularen Ansatz können Sie leicht Folgendes erreichen:

  • Lose Kopplung zwischen Komponenten
  • Klare Verträge und Abhängigkeiten zwischen Komponenten
  • Versteckte Implementierung mit starker Kapselung

Das Hauptelement Ihrer Implementierung ist das Modul. Entwickler können ihren Code in einer modularen Struktur organisieren, in der Abhängigkeiten innerhalb ihrer jeweiligen Moduldefinitionsdateien angegeben werden.

Die Eigenschaften eines Moduls werden als Datei mit dem Namen module-info.java definiert, die die folgenden Attribute enthält:

  • Der Modulname
  • Die Pakete des Moduls, die Sie öffentlich verfügbar machen möchten
  • Die direkten oder transitiven Abhängigkeiten, von denen das Modul abhängig ist
  • Die Liste der Dienste, die das Modul verwendet
  • Alle möglichen Implementierungen des Dienstes, den das Modul bietet

Die folgenden Schlüsselwörter werden zum Festlegen der Hauptmerkmale eines Moduls über die Datei module-info.java verwendet:

  • module: Die Moduldefinitionsdatei beginnt mit diesem Schlüsselwort, gefolgt von seinem Namen und seiner Definition.
  • supplies ... with ...: Mit dem Schlüsselwort wird wird angegeben, dass das Modul Implementierungen für eine definierte Serviceschnittstelle bereitstellt. Die Service-Schnittstelle wird mit dem Schlüsselwort with ausgedrückt. Siehe Java 9-Modularität: Erster Blick
  • Requires: Dieses Schlüsselwort wird verwendet, um die Abhängigkeiten der Module anzuzeigen. Nach diesem Schlüsselwort muss ein Modulname angegeben werden. Die Liste der Abhängigkeiten wird durch mehrere erforderliche Anweisungen festgelegt.
  • transitiv: Dieses Schlüsselwort wird nach dem Schlüsselwort Requires gesetzt. Mit dieser Funktion erklären Sie, dass jedes Modul, das von der Definition des Moduls abhängt, transitive benötigt, eine implizite Abhängigkeit vom hat.
  • use: Dieses Schlüsselwort gibt die Service-Schnittstelle an, die dieses Modul verwendet. Nach diesem Schlüsselwort muss ein Typenname mit vollständig qualifizierten Klassen- oder Schnittstellennamen angegeben werden.
  • opens: Mit diesem Schlüsselwort werden die Pakete angegeben, auf die nur zur Laufzeit zugegriffen werden kann. Sie können sie auch für die Introspektion verwenden, indem Sie Reflection-APIs verwenden. Dies ist sehr wichtig für Bibliotheken und Frameworks, die Reflection-APIs verwenden, um so abstrakt wie möglich zu sein. Die opens-Direktive kann auch auf Modulebene gesetzt werden. In diesem Fall sind alle Pakete des Moduls zur Laufzeit verfügbar.
  • exports: Mit diesem Schlüsselwort werden die öffentlich verfügbaren Pakete des Moduls angegeben. Nach diesem Schlüsselwort muss ein Paketname angegeben werden. Sie können außerdem Java 9-Modularität: Erste Schritte von Sander Mak sehen, um mehr über das Modul zu erfahren

Java-Puzzle im Vergleich zu OSGi

Die zwei Ansätze, Java Jigsaw-Modul und Open Service Gateway Initiative (OSGi), weisen jedoch einige Unterschiede auf:

  • Die Einführung von OSGi beruht im Wesentlichen auf der Unterstützung der dynamischen Komponentensteuerung. In diesem Fall werden Plugins oder Komponenten dynamisch geladen und dann nach Bedarf aktiviert, deaktiviert und sogar aktualisiert oder entfernt. Derzeit ist dieser dynamische Modullebenszyklus für Java-Module nicht verfügbar.
  • Im Vergleich zu Java-Modulen unterstützt OSGi eine verbesserte Versionierung. Andere OSGi-Vorteile beziehen sich auf die Isolation. Bei Paketänderungen müssen beispielsweise nur die direkten Abhängigkeiten neu kompiliert werden, wohingegen der gesamte Layer eines Java-Moduls zusammen mit allen untergeordneten Layern neu kompiliert werden muss, wenn sich nur ein Modul ändert.
  • Der Nachteil ist, dass für OSGi-Bundles weiterhin Probleme mit dem Klassenpfad auftreten, beispielsweise Laufzeitausnahmen für fehlende Abhängigkeiten oder das Laden beliebiger Klassen für Pakete mit demselben Namen.
  • OSGi erfordert außerdem einen Klassenlader pro Modul, der sich auf einige Bibliotheken auswirken kann, die nur einen einzelnen Klassenlader erwarten. Java-Module lassen keine Split-Pakete zu, die insgesamt eine große Verbesserung in Java darstellen und keine ähnlichen Klassenlader-Anforderungen oder -Beschränkungen aufweisen. Ein großer Vorteil von Java-Modulen gegenüber OSGi ist die Compiler-Unterstützung.

Wir können die Modularisierung der Anwendungskomponenten in der Microservice-Architektur optimal nutzen und das Beste aus beiden Technologien kombinieren.

Die Gesamtstrategie besteht darin, Java-Module zu verwenden, um Bibliotheken (entweder importiert oder exportiert) und die JVM selbst zu modularisieren und OSGi darüber zu verwenden, um die Modularität der Anwendung und die dynamische Lebenszyklussteuerung zu handhaben. Siehe Neuerungen in Java 9 - Module und mehr, um mehr darüber zu erfahren.

JDK 10

In JDK 10 wurden einige neue Funktionen für Cloud-Umgebungen und Microservice-Architektur eingeführt. Der erste ist Docker Awareness, der nur für Linux unterstützt wird. Mit dieser Funktion können Sie Containerspezifische Informationen zur Anzahl der CPUs (automatisch) und zum zugewiesenen Speicher (automatisch) extrahieren.

Die folgenden neuen JVM-Konfigurationsparameter wurden eingeführt:

  • -XX: UseContainerSupport: Die JVM wurde aktualisiert, um zu wissen, dass sie in einem Docker-Container ausgeführt wird. Auf diese Weise werden Containerspezifische Konfigurationsinformationen extrahiert und das Betriebssystem nicht abgefragt. Die wichtigsten Informationen, die extrahiert werden, sind der Gesamtspeicher, der dem Container zugewiesen wurde, und die Anzahl der CPUs. Der Wert der für den Java-Prozess verfügbaren CPUs wird aus den angegebenen CPU-Anteilen, CPU-Quoten und CPU-Sätzen berechnet.
  • -XX: ActiveProcessorCount: Dieser Wert überschreibt alle anderen von der JVM automatisch implementierten Logik der CPU-Erkennung.
  • -XX: InitialRAMPercentage / -XX: MaxRAMPercentage / -XX: MinRAMPercentage: Dieser Parameter ermöglicht Benutzern, die die JVM in Docker-Containern ausführen, mehr Kontrolle über den für die Java-Heap-Zuweisung verwendeten Systemspeicher.

Mit dem Parallel Full GC für G1, wie in JEP 307 beschrieben, wird eine große Leistungsverbesserung erzielt. Mit dieser Funktion wird die vollständige GC auf parallelen Threads mit folgenden Vorteilen erzielt:

  • Geringe Wartezeit
  • Hoher Durchsatz
  • Keine / weniger Stop-of-World-Pausen (STW)
  • Verbesserte G1-Latenzzeiten im schlechtesten Fall

Um eine bessere Leistung zu erzielen, wurde mit dem JEP 310 auch Application Class Data Sharing (CDS) eingeführt. Diese Funktion reduziert den Ressourcenbedarf, wenn mehrere JVMs auf demselben physischen Computer ausgeführt werden, und verbessert die Startzeit von Anwendungen.

Darüber hinaus können Prozesse und Anwendungen gemeinsame Klassenmetadaten (Klassendaten) aus einem gemeinsam genutzten Archiv (dem CDS-Archiv) gemeinsam nutzen. Vor Java SE 10 war die Verwendung von CDS nur auf den Bootstrap-Klassenlader beschränkt.

Ein weiteres wichtiges Element in einer Umgebung wie der Cloud, die so ansprechend wie möglich sein muss, ist die in JEP 312 definierte Funktion Thread-Local Handshakes. Dies ist eine neue Methode zum Ausführen eines Rückrufs in Threads, die die Auswirkungen des Erfassens eines Stack-Trace-Beispiels reduziert zum Beispiel für Profilierungsvorgänge.

Dadurch können einzelne Threads billig gestoppt werden, Stopps von STW-Pausen werden reduziert und die GC-Leistung verbessert. Mit der Funktion Thread-Local Handshakes ist es möglich, einzelne Threads und nicht nur alle Threads oder gar keine zu stoppen. Auf diese Weise müssen Sie keinen sicheren Punkt für die globale JVM festlegen, was zu einer großen Leistungsverbesserung führt.

Nicht zuletzt ermöglicht das JDK 10 die Heap-Zuordnung auf alternativen Geräten, wie in JEP 316 beschrieben. Weitere Informationen zu Java 10-Funktionen finden Sie unter Neuerungen in Java 10.

Diese großartige Funktion, die mit Intel realisiert wurde, ermöglicht es der JVM, den zum Speichern von Java-Objekten erforderlichen Heap auf einem vom Benutzer angegebenen anderen Speichergerät zuzuordnen, beispielsweise einem nichtflüchtigen Dual-In-Line-Speichermodul (NVDIMM).

Dieser Aspekt kann in einer Multi-JVM-Umgebung äußerst wichtig sein, in der Sie die Prozesse mit niedrigerer Priorität anweisen, den NVDIMM-Speicher zu verwenden, während die Prozesse mit höherer Priorität die Verwendung von DRAM (Dynamic Random Access Memory) anweisen.

Bei den hier beschriebenen Funktionen handelt es sich nur um einen kleinen Satz der in JDK 9 und 10 veröffentlichten neuen Funktionen, die den großen Aufwand zur Verbesserung der Java-Sprache demonstrieren und eine gute Wahl für die Implementierung von Microservice in Cloud-Umgebungen machen.

Im September 2018 wurde JDK 11 mit einigen neuen großartigen Funktionen wie Epsilon - einem No-Op-Garbage Collector - veröffentlicht. Haben Sie immer noch Zweifel an der Verwendung von Java für neue Microservice-Architekturen?

Wenn Sie Hands-On Cloud-Native Microservices mit Jakarta EE näher kennenlernen können, erfahren Sie, wie Sie mithilfe der Cloud-basierten Microservice-Architektur dynamisch skalierbare Anwendungen erstellen können, indem Sie die am häufigsten verwendeten und verwendeten Laufzeitumgebungen verwenden.

Hands-On Cloud-Native Microservices mit Jakarta EE

Praktische Cloud-Native Microservices mit Jakarta EE helfen Ihnen, über die erforderlichen Fähigkeiten zu verfügen, um äußerst robuste Anwendungen mithilfe der Cloud-basierten Microservice-Architektur zu erstellen.

Schlussnotizen

Danke, Sie haben es bis zum Ende des Artikels geschafft ... Viel Erfolg beim Cloud Computing mit Java! Es wird sicherlich nicht einfach sein, aber durch die Verwendung dieser Funktionen und Anleitungen wird es weniger schmerzhaft

Wenn Ihnen dieser Artikel gefällt, teilen Sie ihn bitte mit Ihren Freunden und Kollegen. und @ Javarevisited auf Medium

Siehe auch

Demystifying Tech BurnoutAuf der Suche nach sinnvoller Arbeit: Ich stieg von 105.000 USD pro Jahr auf 15 USD / Stunde MindestlohnAdam: Rebell mit einer UrsacheDie Möglichkeit, „Klick-Köder“ -Inhalte zu erstellen, wurde mit einem frühzeitigen kognitiven Verfall…Frauen von TextNow: LindsayWie wir eine schnelle Antwortzeit für die Kartenautorisierung gewährleisten