Jak uzyskać dostęp do niewyeksportowanego modułu Java?

Aug 27 2020

Muszę zlokalizować wbudowane kontrolki JavaFX. Przed Jigsawa były sposoby na osiągnięcie tego:

  1. Poprzez dodatkowy plik właściwości, który należy umieścić w com.sun.javafx...pakiecie
  2. Poprzez odbicie API, jak pokazano tutaj

Obie metody nie są kompatybilne z modułami Java, ponieważ com/sun/javafx/scene/control/*nie są częścią publicznego API i nie ma możliwości utworzenia dwóch pakietów o identycznej nazwie, nawet jeśli należą do różnych projektów.

Jest jakaś szansa na włamanie się do tego problemu, aby uzyskać dostęp do pakietu wewnętrznego? Dokładniej, moduł ładujący klasy ControlResources .

Powiązane pytania:

Lokalizowanie kontrolek JavaFx

Odpowiedzi

Evan Aug 28 2020 at 13:00

Ok, straciłem cały dzień kopiąc ten temat.

Krótka odpowiedź: to niemożliwe.

Długa odpowiedź

Możesz używać add-exportsi, add-opensaby uzyskać dostęp do com.sun.javafx.scene.control.skin.resources, ale będzie to działać tylko wtedy, gdy nie używasz nazwanych modułów, innymi słowy, twoja aplikacja nie może być modularyzowana.

<plugin>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-maven-plugin</artifactId>
    <configuration>
        <mainClass>${bld.mainClass}</mainClass> <executable>${java.home}/bin/java</executable>
        <options>
            <option>--add-exports</option>
            <option>javafx.controls/com.sun.javafx.scene.control.skin.resources=app.module</option>
            <option>--add-opens</option>
            <option>javafx.controls/com.sun.javafx.scene.control.skin.resources=app.module</option>
        </options>
    </configuration>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <compilerArgs>
            <arg>--add-exports</arg>
            <arg>javafx.controls/com.sun.javafx.scene.control.skin.resources=app.module</arg>
            <arg>--add-opens</arg>
            <arg>javafx.controls/com.sun.javafx.scene.control.skin.resources=app.module</arg>
        </compilerArgs>
    </configuration>
</plugin>

Jeśli Twoja aplikacja jest zmodularyzowana, otrzymasz to.

Caused by: java.lang.UnsupportedOperationException: ResourceBundle.Control not supported in named modules
    at java.base/java.util.ResourceBundle.checkNamedModule(ResourceBundle.java:1547)
    at java.base/java.util.ResourceBundle.getBundle(ResourceBundle.java:1508)

Dzieje się tak, ponieważ jedynym sposobem uzyskania dostępu do zasobów znajdujących się w innym module jest SPI ( dokumentacja tutaj ). OpenJFX nie jest implementowany w ResourceBundleProvidercelu zapewnienia dostępu do internacjonalizacji kontroli, ponieważ jest częścią wewnętrznego API.

Tak więc ten problem mogą rozwiązać tylko deweloperzy OpenJFX, ale sądząc po ostatnich dziennikach zmian OpenJFX, są oni bardzo skoncentrowani na poprawianiu literówek, a nie funkcji.