2016-11-15 3 views
6

Verschiedene Ressourcen (infoq, jigsaw-dev, osdir) zeigen an, dass das gleiche Paket in verschiedenen Java-Modulen zu einem LayerInstantiationException führt, auch wenn die Pakete intern im Modul sind (nicht exportiert).
Dies scheint genau das Gegenteil von dem, was die requirements sagen:Java 9 überlappende nicht exportierte Pakete

Die Java-Compiler, eine virtuelle Maschine und System-Zeit laufen muß sicherstellen, dass Module, die Pakete mit dem gleichen Namen enthält nicht miteinander interferieren . Wenn zwei unterschiedliche Module Pakete mit demselben Namen enthalten, werden aus der Perspektive jedes Moduls alle Typen und Mitglieder in diesem Paket nur von diesem Modul definiert.

Sind zwei Module, die von einer App verwendet werden, in der Lage, private Pakete mit demselben Namen zu enthalten?

EDIT
Dies ist ein issue von JMPS wie von Stanislav Lukyanov wies

Antwort

1

Diese Definition ist offen für Interpretation. Es bleibt korrekt, da Jigsaw sicherstellt, dass zwei Module nie gemeinsam genutzte Pakete definieren, indem sie das Laden der Klasse im Falle eines solchen Konflikts abbrechen.

Wenn Sie in die Klassenladeprogrammimplementierung von Java 9 schauen, können Sie sehen, dass ein Paketname von einem einzelnen Modul zugeordnet wird. Es ist daher unmöglich, zwei haben zwei Module, um das Eigentum zu erklären. Es ist jedoch möglich, dass zwei Klassenlader in einer Kind-Eltern-Beziehung das gleiche Paket definieren.

+0

Ich würde sagen, dass die beiden Klassenlader nicht in einer Eltern-Kind-Beziehung sein sollten, weil das bedeutet, dass das Kind zuerst die Eltern nach der Klasse/Paket fragt und erst dann versucht, es selbst zu laden (oder umgekehrt)) – Bax

+1

Um dies zu vermeiden, hat Java 9 die 'getPackage' Methode zugunsten der 'getDefinedPackage' Methode veraltet.Der gleiche Paketname von zwei verschiedenen Klassenladern wird auch heute nicht als gleich angesehen; Wenn Sie beispielsweise A von B ableiten, kann B package-private Methoden von A nicht überschreiben, wenn es in einem anderen Klassenlader geladen wurde. Wenn das übergeordnete Element nicht die gleiche Klasse (!) Definiert, gibt es kein Problem, wenn das gleiche Paket verwendet wird, da es nicht gleich ist. Dieses Problem tritt nur auf, wenn Pakete von zwei Modulen innerhalb desselben Klassenladeprogramms definiert werden. –

+0

wird jedes Modul standardmäßig von einem anderen Klassenlader geladen? – Bax

5

Wie in den von Ihnen verlinkten Diskussionen erwähnt, handelt es sich um eine Zuordnung zwischen Klassenladeprogrammen und Modulen.

Wenn Sie laden zwei Module M1 und M2 beide eine nicht exportiert (aka verdeckt) Paket P über eine Class-Loader enthalten CL JPMS hat eine solche Konfiguration zu verwerfen, da sonst beide Schlüssel JPMS Prinzipien - starke Kapselung und zuverlässige Konfiguration - könnte kaputt sein. Durch das Auslösen einer Ausnahme implementiert JPMS die Anforderung, die Sie angegeben haben, und stellt sicher, dass während der Ausführung keine Konflikte später auftreten.

Auf der anderen Seite, wenn Sie M1 und M2 über zwei Ladern CL1 und CL2 sind Laden Sie tatsächlich zwei Laufzeitpakete {CL1, P} und {CL2, P} zu schaffen, so dass es keine Kollision und die Layer instanziiert werden kann.

Das Usability-Problem hier ist, dass java einzelnen Lader für alle Module der Anwendungsschicht verwendet (die "startende", erstellt von den Befehlszeilenargumenten), die zu LayerInstantiationException führt. Das ist derzeit ein offenes Thema auf der JPMS-Liste, siehe [hier] (http://openjdk.java.net/projects/jigsaw/spec/issues/#AvoidConcealedPackageConflicts). Aber unabhängig von der Problemlösung sollten Sie, falls erforderlich, in der Lage sein, die geteilten Pakete zu bearbeiten, indem Sie eine kleine Hauptklasse schreiben, die die benötigte Configuration erstellt (Übrigens wird ein JPMS-fähiger Anwendungscontainer dies wahrscheinlich für Sie tun).