getDeclaredField

kenai1348u

Mitglied
Hallo,

bei folgender Methode:

private void loadDatabase() {
// Declare a few local variables for later use
ClassLoader currentClassLoader = null;
Field cacheField = null;
boolean cacheValue = true;

try {
// Store the current ClassLoader, so it can be reverted later
currentClassLoader = Thread.currentThread().getContextClassLoader();

// Set the ClassLoader to Plugin ClassLoader
Thread.currentThread().setContextClassLoader(classLoader);

// Get a reference to the private static "defaultUseCaches"-field in
// URLConnection
cacheField = URLConnection.class.getDeclaredField("defaultUseCaches");

// Make it accessible, store the default value and set it to false
cacheField.setAccessible(true);
cacheValue = cacheField.getBoolean(null);
cacheField.setBoolean(null, false);

// Setup Ebean based on the configuration
ebeanServer = EbeanServerFactory.create(serverConfig);
} catch (Exception ex) {
throw new RuntimeException("Failed to create a new instance of the EbeanServer", ex);
} finally {
// Revert the ClassLoader back to its original value
if (currentClassLoader != null) {
Thread.currentThread().setContextClassLoader(currentClassLoader);
}

// Revert the "defaultUseCaches"-field in URLConnection back to its
// original value
try {
if (cacheField != null) {
cacheField.setBoolean(null, cacheValue);
}
} catch (Exception e) {
System.out.println("Failed to revert the \"defaultUseCaches\"-field back to its original value, URLConnection-caching remains disabled.");
}
}
}


gibt es beim fett markierten Punkt einen Fehler:Unable to make field private static volatile boolean java.net.URLConnection.defaultUseCaches accessible: module java.base does not "opens java.net" to unnamed module @5e9f7335

Was kann ich da tun? LG
 

KonradN

Super-Moderator
Mitarbeiter
Das Problem ist hier das Modulsystem, welches mit Java 9 eingeführt wurde. Der Zugriff auf Klassen per Reflection ist eingeschränkt. Damit dies möglich ist, muss ein Modul sich öffnen für sowas.

Das Modul java.net ist ja vom JDK, d.h. hier wäre eine Möglichkeit beim Aufruf dem Java den Parameter --add-opens mitzugeben. Der Parameter wird angezeigt, wenn Du mal java -X aufrufst:
Code:
    --add-opens <Modul>/<Package>=<Zielmodul>(,<Zielmodul>)*
                      Aktualisiert <Modul>, um <Package> in
                      <Zielmodul> zu öffnen, ungeachtet der Moduldeklaration.

Die Fehlermeldung beinhaltet eigentlich alles:
Modul ist java.base
Package ist java.net
Zielmodul ist nicht benannt (Du hast keine module-info.java), daher ist das ALL-UNNAMED hier anzugeben.

Daher wird beim Aufruf der Parameter benötigt: --add-opens java.base/java.net=ALL-UNNAMED
 

kenai1348u

Mitglied
Das Problem ist hier das Modulsystem, welches mit Java 9 eingeführt wurde. Der Zugriff auf Klassen per Reflection ist eingeschränkt. Damit dies möglich ist, muss ein Modul sich öffnen für sowas.

Das Modul java.net ist ja vom JDK, d.h. hier wäre eine Möglichkeit beim Aufruf dem Java den Parameter --add-opens mitzugeben. Der Parameter wird angezeigt, wenn Du mal java -X aufrufst:
Code:
    --add-opens <Modul>/<Package>=<Zielmodul>(,<Zielmodul>)*
                      Aktualisiert <Modul>, um <Package> in
                      <Zielmodul> zu öffnen, ungeachtet der Moduldeklaration.

Die Fehlermeldung beinhaltet eigentlich alles:
Modul ist java.base
Package ist java.net
Zielmodul ist nicht benannt (Du hast keine module-info.java), daher ist das ALL-UNNAMED hier anzugeben.

Daher wird beim Aufruf der Parameter benötigt: --add-opens java.base/java.net=ALL-UNNAMED
Vielen lieben Dank für die schnelle Antwort!:D

Sie haben mir SEHR geholfen. Danke vielmals.
 
Zuletzt bearbeitet:
Wollte gerade schreiben, du hast erst mit neueren Java-Versionen das Problem, bis ich bemerkt hatte, Konrado kam mir zuvor. 🤣

Aber das soll nicht bedeuten, dass man deshalb auf Java 8 umstellen sollte. ;) (Nur weil die Zeilenargumente kompliziert sind )
 

KonradN

Super-Moderator
Mitarbeiter
Die Frage ist, ob man so einen Hack wirklich braucht / will. Wenn man bei einer Klasse auf ein inneres Feld zugreift dann würde ich dies erst einmal nicht als saubere Lösung ansehen. Und Java 9 gibt es ja schon etwas länger - evtl. haben die verwendeten Technologien da inzwischen auch neue Versionen, so dass sowas nicht mehr notwendig ist.
 

kenai1348u

Mitglied
Danke für Eure Antworten!
Tatsächlich verbinde ich mich mit dieser Methode in eine Datenbank wie folgt und habe es nicht selber geschrieben. Es handelt sich um Ebean für Java, was mir die Arbeit sehr leicht macht und ich deswegen nicht darauf verzichten kann.

Kann dies aber zu Performanceprobleme o. Ä. führen, bzw. wie wäre es möglich, es "sauber" zu lösen?
 

KonradN

Super-Moderator
Mitarbeiter
Du solltest deinen Code in so gern prüfen, ob so ein Hack überhaupt noch notwendig ist.

Ich habe da jetzt verstanden, dass es damals bei Nutzung von ebean zu irgendwelchen Problemen gekommen ist und dies ein Workaround war, die Probleme zu beheben.

Das Problem ist, dass der Workaround auf ein private Field zugreift um dies zu setzen. Die Implementation ist aber aus gutem Grund gekapselt. Diese Kapselung zu durchbrechen kann zu Problemen führen, wenn die Implementation geändert wird.

Weiterhin ist diese Anpassung etwas, das nicht zwingend funktionieren muss. Reflection hat z.B. Einschränkungen, wenn jemand mit GraalVM/Native arbeiten möchte.

Die Folgen sind somit:
Bei jedem JDK kamn es sein, deine Software nicht mehr geht, weil da die Implementation angepasst wurde.
Und mit GraalVM/native dürfte es schon eine Umgebung geben, die zumindest nicht out of the box direkt funktionieren wird (wäre meine Erwartungshaltung).

Daher wäre mein Tipp, dass du prüfst, ob das so noch notwendig ist und wenn die alten Probleme noch existieren: ob es dafür evtl. eine bessere Lösung gibt.
 

Neue Themen


Oben