© Excellent backgrounds/Shutterstock.com
Teil 4: Die Zukunft des Java Memory Model

Auf dem Prüfstand


Das Java Memory Model (JMM) ist schon zwölf Jahre alt. Viele Konzepte und Vorgehensweisen sind nicht mehr ausreichend gedeckt. Es ist Zeit, einen kritischen Blick darauf zu werfen.

Das letzte Update erfolgte mit der Einführung von Java 5 in Form des JSR 133, wo unter anderem das Verhalten von volatile-Variablen vollständig formal beschrieben wurde. Zum Zeitpunkt der Veröffentlichung des JSR 133 existierte Java schon sein mehr als zehn Jahren. Eine der wichtigsten Aufgaben bestand also darin, die Kompatibilität mit dem bestehenden Code zu gewährleisten [1]. Im Laufe der Zeit hat sich eine Reihe von Baustellen geöffnet, die eine Erweiterung des JMM in Aussicht stellt. Die wichtigsten Beweggründe wurden im Rahmen des JEP 188: Java Memory Model Update beschrieben [2]:

  • Formalisierung der Spezifikation

  • Spezifizieren von später dazugekommenen und über API verfügbaren Operationen wie weakCompare­AndSet

  • Kompatibilität mit später veröffentlichtem Memory Model von C++ 11 – vor allem in Bezug auf native Aufrufe

  • Testing- und Tooling-Support

Nach dem heutigen Stand im Mai 2017 wird im Rahmen des JDK 9 im Sommer keine formale Neuausrichtung des JMM erfolgen. Nichtsdestotrotz wurden viele der angestrebten Ziele des JEP 188 ganz oder zum Teil in Form von Tooling und API-Erweiterungen erreicht.

Atomic-64-Bit-Operationen

Die meiste Hardware unterstützt 64-Bit-atomare Operationen. Dazu zählen auch viele 32-Bit-Architekturen. Die von der Java-Syntax verlangten Zusicherungen in Form von volatile sind dadurch wesentlich aufwendiger und langsamer, als es für die darunterliegende Architektur notwendig wäre. Je nach Hardware ist die eingebaute atomare 64-Bit-Zuweisung zwischen zweimal (ARM7, 32 Bit) und zehnmal (x86, 64 Bit) schneller [3] als volatile. Die Java-Syntax bietet keine andere Möglichkeit für den atomaren 64-Bit-Zugriff, als die Instanzvariable als volatile zu deklarieren. Es gibt Wege, wie man von der Hardwareunterstützung direkt profitieren kann. Einer davon wäre Oracles native, nicht dokumentierte Klasse sun.misc.Unsafe. Seit JDK 6 existiert auch eine „legale“ Möglichkeit. Die Klasse AtomicLong, die eine Alternative zu volatile ist, bietet die Methode lazySet. Das gilt natürlich auch für die anderen atomic-Klassen, wie AtomicInteger oder AtomicReference. Man muss hier explizit erwähnen, dass, obwohl die Methode lazySet ein Bestandteil des API ist, sie sehr sparsam dokumentiert ist. Die Methodenbeschreibung ist nicht an die Spezifikation angelehnt, und die genaue Arbeitsweise, z. B. in Bezug auf Memory-Barrieren, bleibt dem JVM-Anbieter überlassen. Es lässt viel Spielraum und kann je nach JVM-Release anders funktionieren. Moderne Hardware bietet auch andere performanceoptimierende Tricks. Einer davon ist weakCompareAndSet. Als Preis für die bessere Performance kann diese Methode fälschlicherweise false zurückgeben. Diese (wie auch andere lazy-Methoden) ist mit Vorsicht zu genießen und ausführlich zu testen. Sie ist nicht formal durch die Spezifikation abgedeckt und sehr sparsam beschrieben. Es wäre dadurch zu erwarten, dass das Verhalten je nach Hardware und JVM-Anbieter unterschiedlich sein kann. Es erscheint sinnvoll, wenn diese Gruppe von Methoden in einer der nächsten JMM-Spezifikationen ihren Platz findet.

Die Memory-Barriere

Die Java-Spezifikation versteckt das komplette Memory-Management vor dem Entwickler. Es war bis jetzt nicht möglich, mittels offiziellem Java-API die Memory-Barriere selber zu setzen. Es wurde dem nativen Code überlassen. Diese Einschränkung hatte nicht nur negative Seiten. Schauen wir uns ein Beispiel in Listing 1 aus dem Artikel von Aleksey Shipilëv an [4].

Listing 1: Verhalten einer volatilen Variablen

int x, y; -- CPU 1 -- Unsafe.fullFence(); x = 1; Unsafe.fullFence(); -- CPU 2 -- Unsafe.fullFence(); y = 1; Unsafe.fullFence(); -- CPU 3 -- Unsafe.loadFence(); result.r1 = x; Unsafe.loadFence(); result.r2 = y; Unsafe.loadFence(); -- CPU 4 -- Unsafe.loadF...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang