Es gibt viele Fragen zum illegalen reflektierenden Zugriff in Java 9.
Was ich jetzt nicht finden kann, weil Google nur Leute anspricht, die versuchen, die Fehlermeldungen zu umgehen, ist, was ein illegaler reflektierender Zugriff tatsächlich ist.
Meine ziemlich einfache Frage lautet also:
Was definiert einen illegalen reflektierenden Zugang und welche Umstände lösen die Warnung aus?
Ich habe festgestellt, dass es etwas mit den in Java 9 eingeführten Kapselungsprinzipien zu tun hat, aber wie alles zusammen hängt und was die Warnung in welchem Szenario auslöst, für das ich keine Erklärung finden kann.
java
java-9
java-module
Tschallacka
quelle
quelle
Antworten:
Abgesehen von einem Verständnis der Zugriffe zwischen Modulen und ihren jeweiligen Paketen. Ich glaube, der Kern davon liegt im Modulsystem # Relaxed-strong-encapsulation, und ich würde nur die relevanten Teile davon auswählen, um zu versuchen, die Frage zu beantworten.
Um die Migration auf Java-9 zu unterstützen, könnte die starke Kapselung der Module gelockert werden.
Eine Implementierung kann statischen Zugriff bereitstellen , dh durch kompilierten Bytecode.
Kann eine Möglichkeit bieten, sein Laufzeitsystem mit einem oder mehreren Paketen eines oder mehrerer seiner Module aufzurufen, die für den Code in allen unbenannten Modulen geöffnet sind , dh für den Code im Klassenpfad. Wenn das Laufzeitsystem auf diese Weise aufgerufen wird und wenn dadurch einige Aufrufe der Reflection-APIs erfolgreich sind, wo sie sonst fehlgeschlagen wären.
In solchen Fällen haben Sie tatsächlich einen reflektierenden Zugriff vorgenommen, der "illegal" ist, da Sie in einer rein modularen Welt solche Zugriffe nicht durchführen sollten.
Diese Lockerung der Kapselung wird zur Laufzeit durch eine neue Launcher-Option gesteuert,
--illegal-access
die in Java9 standardmäßig gleich istpermit
. Derpermit
Modus sorgt dafürDie Modi können mit Werten
debug
(Nachricht sowie Stapelverfolgung für jeden solchen Zugriff),warn
(Nachricht für jeden solchen Zugriff) unddeny
(deaktiviert solche Operationen) konfiguriert werden .Einige Dinge, die zum Debuggen und Beheben von Anwendungen erforderlich sind, sind:
--illegal-access=deny
, um zu erfahren, wie Sie Pakete von einem Modul zum anderen öffnen können , ohne eine Moduldeklaration mit einer solchen Direktive (opens
) oder einer expliziten Verwendung von--add-opens
VM arg.jdeps
Tools mit der--jdk-internals
Option identifiziert werdenFragen zu einer solchen Beispielwarnung: = JDK9: Es ist eine unzulässige reflektierende Zugriffsoperation aufgetreten. org.python.core.PySystemState
Der letzte und wichtige Hinweis: Während Sie sicherstellen möchten, dass Sie nicht vor solchen Warnungen stehen und zukunftssicher sind, müssen Sie lediglich sicherstellen, dass Ihre Module keine illegalen reflektierenden Zugriffe ausführen. :) :)
quelle
Ich habe einen Oracle- Artikel zum Java 9-Modulsystem gefunden
Wie unter https://stackoverflow.com/a/50251958/134894 ausgeführt , sind die Unterschiede zwischen
AccessibleObject#setAccessible
JDK8 und JDK9 aufschlussreich. Insbesondere JDK9 hinzugefügtDies unterstreicht die Bedeutung von Modulen und deren Exporten (in Java 9).
quelle
–illegal-access=permit
...fun
Schauen Sie sich einfach die
setAccessible()
Methode an, mit der aufprivate
Felder und Methoden zugegriffen wird:https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible-boolean-
https://docs.oracle.com/javase/9/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible-boolean-
Jetzt sind viel mehr Bedingungen erforderlich, damit diese Methode funktioniert. Der einzige Grund, warum fast die gesamte ältere Software nicht beschädigt wird, besteht darin, dass Module, die automatisch aus einfachen JARs generiert werden, sehr zulässig sind (alles für alle öffnen und exportieren).
quelle
Wenn Sie die Option zum Hinzufügen und Öffnen verwenden möchten, finden Sie hier einen Befehl, um herauszufinden, welches Modul welches Paket bereitstellt ->
java --list-modules | tr @ " " | awk '{ print $1 }' | xargs -n1 java -d
Der Name des Moduls wird mit dem @ angezeigt, während der Name der Pakete ohne das @ angezeigt wird
HINWEIS: getestet mit JDK 11
WICHTIG: Offensichtlich ist besser als der Anbieter des Pakets den illegalen Zugriff nicht macht
quelle