如何访问未导出的 Java 模块?

How to get access to unexported Java module?

我需要本地化 JavaFX 内置控件。在 Jigsaw 之前,有一些方法可以实现这一点:

  1. 通过额外的 properties file 必须放入 com.sun.javafx...
  2. 通过反射 API,如图所示 here

这两种方法都与 Java 模块不兼容,因为 com/sun/javafx/scene/control/* 不是 public API 的一部分并且无法创建两个具有相同名称的包,即使它们属于不同的项目。

是否有机会破解此问题以访问内部包?更具体地说 ControlResources 类加载器。

相关问题:

Localizing JavaFx Controls

好吧,我花了一整天的时间来挖掘这个话题。

简答:不可能。

长答案

您可以使用 add-exportsadd-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 (docs here)。 OpenJFX 没有实现 ResourceBundleProvider 来提供对控件国际化的访问,因为它是内部 API.

的一部分

因此,这个问题只能由 OpenJFX 开发人员解决,但从最近的 OpenJFX 变更日志来看,他们高度专注于修复拼写错误,而不是功能。