Как получить доступ к неэкспортируемому модулю Java?

Aug 27 2020

Мне нужно локализовать встроенные элементы управления JavaFX. До Jigsaw этого можно было добиться:

  1. Через файл дополнительных свойств, который нужно поместить в com.sun.javafx...пакет
  2. Через API отражения, как показано здесь

Оба метода несовместимы с модулями Java, потому что com/sun/javafx/scene/control/*не являются частью общедоступного API, и невозможно создать два пакета с одинаковым именем, даже если они принадлежат разным проектам.

Есть ли шанс взломать эту проблему, чтобы получить доступ к внутреннему пакету? В частности, загрузчик классов ControlResources .

Связанные вопросы:

Локализация элементов управления JavaFx

Ответы

Evan Aug 28 2020 at 13:00

Ладно, я целый день копался в этой теме.

Короткий ответ: это невозможно.

Длинный ответ

Вы можете использовать add-exportsи add-opensдля получения доступа к com.sun.javafx.scene.control.skin.resources, но это будет работать только в том случае, если вы не используете именованные модули, другими словами, ваше приложение не должно быть модульным.

<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>

Если ваше приложение построено на модулях, вы получите это.

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)

Это связано с тем, что единственный способ получить доступ к ресурсам, расположенным в другом модуле, - это SPI ( документы здесь ). OpenJFX не реализуется ResourceBundleProviderдля обеспечения доступа к интернационализации элементов управления, потому что это часть внутреннего API.

Таким образом, эту проблему могут решить только разработчики OpenJFX, но, судя по последним журналам изменений OpenJFX, они сосредоточены на исправлении опечаток, а не на функциях.