如何访问未导出的 Java 模块?
How to get access to unexported Java module?
我需要本地化 JavaFX 内置控件。在 Jigsaw 之前,有一些方法可以实现这一点:
- 通过额外的 properties file 必须放入
com.sun.javafx...
包
- 通过反射 API,如图所示 here
这两种方法都与 Java 模块不兼容,因为 com/sun/javafx/scene/control/*
不是 public API 的一部分并且无法创建两个具有相同名称的包,即使它们属于不同的项目。
是否有机会破解此问题以访问内部包?更具体地说 ControlResources 类加载器。
相关问题:
Localizing JavaFx Controls
好吧,我花了一整天的时间来挖掘这个话题。
简答:不可能。
长答案
您可以使用 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 (docs here)。 OpenJFX 没有实现 ResourceBundleProvider
来提供对控件国际化的访问,因为它是内部 API.
的一部分
因此,这个问题只能由 OpenJFX 开发人员解决,但从最近的 OpenJFX 变更日志来看,他们高度专注于修复拼写错误,而不是功能。
我需要本地化 JavaFX 内置控件。在 Jigsaw 之前,有一些方法可以实现这一点:
- 通过额外的 properties file 必须放入
com.sun.javafx...
包 - 通过反射 API,如图所示 here
这两种方法都与 Java 模块不兼容,因为 com/sun/javafx/scene/control/*
不是 public API 的一部分并且无法创建两个具有相同名称的包,即使它们属于不同的项目。
是否有机会破解此问题以访问内部包?更具体地说 ControlResources 类加载器。
相关问题:
Localizing JavaFx Controls
好吧,我花了一整天的时间来挖掘这个话题。
简答:不可能。
长答案
您可以使用 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 (docs here)。 OpenJFX 没有实现 ResourceBundleProvider
来提供对控件国际化的访问,因为它是内部 API.
因此,这个问题只能由 OpenJFX 开发人员解决,但从最近的 OpenJFX 变更日志来看,他们高度专注于修复拼写错误,而不是功能。