Lessons Learned

Was wir aus der Misere um sun.misc.Unsafe lernen können

Lukas Eder

© Shutterstock.com/Oleksandr Berezko

Die Debatte um das Entfernen von sun.misc.Unsafe aus Java 9 wird uns noch eine ganze Weile begleiten. In diesem Gastbeitrag vom jOOQ-Blog klinkt sich Lukas Eder in die Diskussion ein und legt dar, welche Lektion wir daraus lernen können.

Oracle wird die interne sun.misc.Unsafe-Klasse in Java 9 entfernen. Während die meisten Entwickler dieser Änderung eher gleichgültig gegenüberstehen dürften, gilt dies für andere nicht – vor allem für Entwickler von Bibliotheken. So finden sich in der Blogosphäre einige Artikel, die ein ziemlich düsteres Bild von einer Zukunft ohne sun.misc.Unsafe zeichnen:

Das Unterhalten eines öffentlichen APIs gestaltet sich außerordentlich schwierig, vor allem wenn es um ein derart populäres API wie das des JDK geht. Es gibt einfach (fast) keine Möglichkeit, um zu verhindern, dass die Leute sich selbst ins Knie schießen. Oracle (und zuvor Sun) haben die sun.*-Packages immer als intern deklariert und klargestellt, dass man sie nicht verwenden soll. Um aus der Seite „Why Developers Should Not Write Programs That Call ‘sun’ Packages“ zu zitieren:

The sun.* packages are not part of the supported, public interface.

A Java program that directly calls into sun.* packages is not guaranteed to work on all Java-compatible platforms. In fact, such a program is not guaranteed to work even in future versions on the same platform.

Diese Erklärung ist nur eine von zahlreichen ähnlich gelagerten Warnungen und Disclaimern. Wer auch immer Unsafe nutzt, tut dies also…. “unsafely”.

Was können wir daraus lernen?

Eine konkrete Lösung für die aktuelle Misere ist derzeit Gegenstand von Diskussionen, ist aber noch nicht gefunden. Eine gute Idee wäre es sicherlich, noch vor der Entfernung von Unsafe einen formalen und öffentlichen Ersatz bereit zu stellen, damit betroffene Bibliotheken Migrationspfade etablieren könnten.

Aber hinter dem Sachverhalt verbirgt sich eine noch viel wichtigere Botschaft. Sie lautet:

Wenn man als Werkzeug nur einen Hammer hat, sieht jedes Problem wie ein Nagel aus.

Auf die Situation hier übertragen bedeutet das: Unsafe ist der Hammer, und angesichts der Tatsache, dass es zwar ein schlechter Hammer ist, aber doch die einzige Option, hatten Bibliotheksentwickler keine große Wahl. Man kann ihnen also nicht wirklich einen Vorwurf machen. Tatsächlich haben sie sich auf ein unsicheres Spiel in einer der stabilsten und abwärtskompatibelsten Softwareumgebungen (= Java) eingelassen und sind für mehr als 10 Jahre gut damit gefahren. Hätten Sie in einer ähnlichen Situation eine andere Wahl getroffen? Oder anders ausgedrückt: War die Entscheidung, auf AWT oder Swing zu setzen, damals eine viel sicherere Wette?

Wenn etwas von jemandem irgendwie genutzt werden kann, dann wird es auch genutzt werden. Dabei ist es völlig egal, wie offensichtlich es ist, dass sich die Leute damit ins eigene Knie schießen. Derzeitig besteht die einzige Möglichkeit, Bibliotheken und/oder APIs zu schreiben und die User vom Zugriff auf die Interna abzuhalten, darin, alles in ein einzelnes Package zu stecken und dort „package-private“ zu deklarieren. Bei jOOQ haben wir das von Anfang an so gehandhabt, da wir genau wussten, dass jOOQs Interna eine sehr heikle Angelegenheit sind und sich ständig verändern können.

Weitere Details zu diesem Grundprinzip finden sich in den folgenden Artikeln:

Allerdings hat diese Lösung einen massiven Nachteil für diejenigen, die die Interna entwickeln: Ergebnis ist nämlich ein Ungetüm von Package, das fast keinerlei Struktur aufweist. Die Entwicklung wird dadurch ziemlich erschwert.

Wie würde also ein besseres Java aussehen?

Die Auswahl an Visibilities in Java war schon immer unzureichend:

  • public
  • protected
  • default (package-private)
  • private

Es sollte eine fünfte Sichtbarkeit geben, die sich genauso verhält wie public, aber den Zugriff von “außerhalb” eines Moduls verhindert. In mancherlei Hinsicht wäre das ein Zwischending zwischen der public– und der default-Sichtbarkeit. Nennen wir dies hypothetisch einmal die module-Sichtbarkeit.

Eigentlich sollten wir nicht nur in der Lage sein, diese Sichtbarkeit auf eine Klasse oder ein Mitglied festzulegen. Darüber hinaus sollten wir in der Lage sein, gegenseitige Abhängigkeiten zwischen Modulen auf einer höheren Ebene zu steuern – genau so, wie es einem die Sprache Ceylon erlaubt:

module org.hibernate "3.0.0.beta" {
import ceylon.collection "1.0.0";
import java.base "7";
shared import java.jdbc "7";
}

Dies ähnelt stark dem Bundle-System von OSGi, in dem Bundles importiert bzw. exportiert werden können. Allerdings ist die obige Modulsyntax viel, viel einfacher als das Konfigurieren von OSGi.

Ein intelligentes Modulsystem würde sogar noch weiter gehen. Es würde nicht nur die Features von OSGi abbilden, sondern auch die von Maven. Mit der Möglichkeit, Abhängigkeiten auf Java-Sprachen-Modul-Basis festzulegen, wären wir vielleicht nicht länger auf die XML-basierten Maven-Deskriptoren angewiesen (oder Gradle bzw. Ant/Ivy), da diese mittels einer einfachen Modulsyntax generiert werden könnten.

Unter diesen Voraussetzungen könnten Klassen wie sun.misc.Unsafe für einige wenige JDK-Module – und nicht für alle – als module-visible deklariert werden. Ich bin mir sicher, dass die Zahl derjenigen, die Reflection missbrauchen, um an die Interna zu gelangen, um 50% sinken würde.

Fazit

Ich hoffe, dass dieses Ceylon-Feature (das übrigens auch in Fantom implementiert ist) in einem zukünftigen Java-Release enthalten sein wird. Einen guten Überblick über die modulare Kapselung von Java 9/Jigsaw bietet der Artikel “The Features Project Jigsaw Brings To Java 9” von Nicolai Parlog.

Bis es soweit ist, sollte allen API-Designern klar sein, dass alle Disclaimer der Welt nicht ausreichen: Die internen APIs werden von euren Nutzern auch weiterhin gebraucht und missbraucht werden. Sie sind vom ersten Tag der Veröffentlichung an ein Teil eures normalen, öffentlichen APIs. Und die Schuld liegt dabei nicht bei euren Nutzern. Das liegt einfach in der Natur der Sache.

Aufmacherbild: Path between desks in a classroom von Shutterstock.com / Urheberrecht: Oleksandr Berezko

Geschrieben von
Lukas Eder
Lukas Eder
Lukas Eder ist leidenschaftlicher Java- und SQL-Entwickler. Er ist Gründer und Leiter der Forschungs- und Entwicklungsabteilung der Data Geekery GmbH, dem Unternehmen hinter jOOQ - die einfachste Art, um SQL in Java zu schreiben.
Kommentare

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu: