Was bedeutet die Verkapselung interner APIs in Java 9?
JEP 260: "Encapsulate Most Internal APIs"
Das JEP 260 ist eine der umstrittensten Neuerungen in Java 9. Dabei ist die Grundidee sehr gut: Entwickler sollen sich in ihren Programmen auf die Verwendung der öffentlichen API beschränken, und nicht auf die Details der konkreten Implementierung. Folgt man diesem Ansatz nicht, so kommt es zu Problemen mit der Portabilität, wenn sich die konkrete Implementierung ändert, oder auf anderen Plattformen anders umgesetzt wird.
Bislang war die Beschränkung auf die öffentliche API nur eine Empfehlung. Der Zugriff auf die Interna war jedoch möglich. Interne APIs erkennt man in der Regel an ihrem Package Namen (z.B. com.sun., sun.misc., etc., anstatt java. oder javax.). Für Java 9 war nun geplant diesen Zugriff standardmässig auch über das Modulsystem (JEP 200) zu verhindern. Das bedeutet, dass auch über Reflection kein Zugriff mehr möglich ist. Für die wichtigsten Sonderfälle, in denen keine entsprechende öffentliche API existiert, sollten Ausnahmen oder neue APIs als Ersatz geschaffen werden.
Umfangreiche Vorbereitungen auf JEP 260
Oracle hat daher in vielen Bereichen versucht die meistverwendeten internen APIs zu identifizieren und öffentliche APIs als Ersatz zu schaffen. Ein Beispiel hierfür sind die VarHandles, welche einige Funktionen von sun.misc.Unsafe übernehmen sollen (JEP 193). Ein anderes Beispiel ist JEP 253 "Prepare JavaFX UI Controls & CSS APIs for Modularization". Bislang war beim Erstellen eigener UI Controls die Verwendung interner APIs (Skin, Behaviour) nötig. In Java 9 gibt es dafür eine öffentliche API.
Widerstand aus der Java Community
Trotz der großen Anstrengungen im Vorfeld, gab es von Anfang an starken Widerstand gegen dieses Vorhaben. Das Problem ist, das einerseits große Umstellungen an bestehenden Projekten nötig werden. Das betrifft Endkunden und noch mehr Tools, die vielfach Reflection nutzen um auf Interna zuzugreifen. Deshalb wurden auch Ausnahmen geschaffen. Das bereits zuvor erwähnte sun.misc.Unsafe wurde zum Beispiel aus diesem Grund von der Beschränkung ausgenommen. Zudem wurde ein "Big Kill-Switch" (--permit-illegal-access) vorgesehen, mit dem auf der Kommandozeile der Zugriff auf Interna per Reflection eingeschaltet werden kann. Dennoch blieb das Thema einer der strittigen Punkte, die in der Abstimmung über JSR 376 zur Ablehnung des EC führte.
Lösung zeichnet sich ab
Inzwischen wurde aber eine Lösung gefunden, der "Big Kill-Switch" ist einfach standardmässig eingeschaltet. Wenn man den illegalen Zugriff dennoch verbieten möchte, muss man den Zugriff auf interne APIs explizit abschalten. Dazu gibt es nun einen Kommandozeilen-Befehl "--illegal-access" geben, der voraussichtlich die Modi "permit", "warn", "debug", und "deny" unterstützt. In der Praxis bedeutet das, dass man sich zwar noch ein wenig Zeit lassen kann, um zum Beispiel vom sun.misc.BASE64Decoder auf eine alterntive Implementierung umzusteigen. Dennoch haben sind in Vorbereitung auf dieses JEP viele interne APIs ersetzt worden, sodass zum Beispiel eigene JavaFX Controls, oder die vielen Hacks, die auf der Klasse Skin basieren angepasst werden müssen.
Besuchen Sie unsere Workshops zum Thema Java 9 um mehr über dieses und weitere neue Features von Java 9 zu erfahren: