IntelliJ 无法使用 OpenJDK 11 识别 JavaFX 11
IntelliJ can't recognize JavaFX 11 with OpenJDK 11
我无法让 IntellJ 识别 JavaFX 包。使用 OpenJDK 11 的新 JavaFX 项目,在尝试构建项目时,IntelliJ 无法识别 JavaFX 包。
我已经从 Maven 存储库导入 openjfx:javafx-base-11
。
我查看了其他问题,解决方案似乎包括检查字节码是否处于正确级别(我的是)以及项目语言是否正确(我的是)。
有人有什么想法吗?
编辑:
错误:
如评论中所述,Starting Guide 是从 Java 11 和 JavaFX 11 开始的地方。
像以前一样工作的关键 Java11 是理解:
- JavaFX 11 不再是 JDK 的一部分
- 您可以以不同的方式获得它,作为 SDK 或作为
常规依赖项 (maven/gradle).
- 即使您的项目不是模块化的,您也需要将其包含到项目的模块路径中。
Java外汇项目
如果您在 IntelliJ 中创建常规 JavaFX 默认项目(没有 Maven 或 Gradle),我建议您从 here 下载 SDK。请注意,也有 jmod,但对于非模块化项目,首选 SDK。
这些是 运行 默认项目的简单步骤:
- 创建一个 JavaFX 项目
- 设置JDK11(指向你本地的Java11版本)
- 添加 JavaFX 11 SDK 作为库。 URL 可能类似于
/Users/<user>/Downloads/javafx-sdk-11/lib/
。执行此操作后,您会注意到 JavaFX 类 现在可以在编辑器中识别。
在你运行默认项目之前,你只需要将这些添加到VM选项:
--module-path /Users/<user>/Downloads/javafx-sdk-11/lib --add-modules=javafx.controls,javafx.fxml
运行
Maven
如果您使用 Maven 构建项目,请按照以下步骤操作:
- 使用 JavaFX 原型创建 Maven 项目
- 设置JDK11(指向你本地的Java11版本)
添加 JavaFX 11 依赖项。
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11</version>
</dependency>
</dependencies>
执行此操作后,您会注意到 JavaFX 类 现在可以在编辑器中识别。
您会注意到 Maven 为您管理所需的依赖项:它会为 javafx.controls 添加 javafx.base 和 javafx.graphics,但最重要的是,它会添加所需的 [=76] =]classifier 基于你的平台。就我而言,Mac.
这就是为什么你的罐子 org.openjfx:javafx-controls:11
是空的,因为存在三种可能的分类器(windows、linux 和 mac 平台),其中包含所有 类 和本机实现。
如果您仍想转到 .m2 存储库并从那里手动获取依赖项,请确保选择正确的(例如 .m2/repository/org/openjfx/javafx-controls/11/javafx-controls-11-mac.jar
)
用 here.
中的插件替换默认的 maven 插件
运行 mvn compile javafx:run
,应该可以。
Gradle 项目也有类似的工作方式,详见 here。
编辑
提到的入门指南包含更新的 documentation 和 IntelliJ 示例项目:
JavaFX 11 没有 Maven/Gradle,参见 non-modular sample or modular sample 个项目。
JavaFX 11 与 Maven,参见 non-modular sample or modular sample 个项目。
JavaFX 11 与 Gradle,参见 non-modular sample or modular sample 个项目。
JavaFX 不再是 JDK 11 的一部分的问题。
以下解决方案适用于 IntelliJ(尚未尝试使用 NetBeans):
添加 JavaFX 全局库作为依赖:
设置 -> 项目结构 -> 模块。在模块中转到
Dependencies 选项卡,并点击添加“+”号 -> Library -> Java->
从列表中选择 JavaFX 并点击添加所选项,然后点击应用设置。
右键单击 JavaFX 项目中的源文件 (src),然后新建一个
模块-info.java 文件。在文件中写入以下代码:
module YourProjectName {
requires javafx.fxml;
requires javafx.controls;
requires javafx.graphics;
opens sample;
}
这 2 个步骤将解决您使用 JavaFX 的所有问题,我向您保证。
参考:The Learn Programming 频道制作了一个 You Tube 教程,将在 5 分钟内解释上述所有细节。我还建议观看它来解决您的问题:
https://www.youtube.com/watch?v=WtOgoomDewo
以上的 None 对我有用。我花了太多时间来清除出现的其他错误。我发现这是最简单也是最好的方法。
This works for getting JavaFx on Jdk 11, 12 & on OpenJdk12 too!
- 该视频向您展示了 JavaFx Sdk 下载
- 如何设置为全局库
- 设置模块-info.java(我更喜欢最下面的那个)
module thisIsTheNameOfYourProject {
requires javafx.fxml;
requires javafx.controls;
requires javafx.graphics;
opens sample;
}
整个过程只花了我 5 分钟 !!!
2020 年 12 月 14 日更新
Intellij 已为 Idea 创建了 new JavaFX project wizard。
我强烈推荐,如果您在使JavaFX项目工作时遇到问题,那么使用新的 JavaFX 项目向导 到:
- 使用向导创建一个新项目。
- 测试新项目是否有效。
- 将旧项目中的相关代码复制到新项目中。
新项目向导非常简单易用,可以在不到一分钟的时间内启动并运行Ning 正常工作的 JavaFX 项目。
向导生成的项目具有以下特点:
- 小型应用程序的简单工作示例代码。
- 使用 JavaFX 图形、控件、fxml。
- 配置 maven 或 gradle 项目以使用 JavaFX,并为基本开发提供适当的 maven 工件依赖项。
- 使用最近的、合理更新的 JavaFX 模块,具有一致的版本(这是许多初学者通常不会做的事情)。
- 添加模块-info.java 文件,适用于基于 FXML 的 JavaFX 应用程序(如果您不使用 FXML 也可以)。
- 演示将 FXML 文件放在资源目录中,并在 运行 时将其作为资源查找(这是很多很多初学者都会犯的错误)。
- 正确地将 Controller class 与 Application class 分开(这也是很多初学者会犯的错误)。
- 演示如何正确使用基于 FXML 文件中的 id 的 @FXML 注入(这也是很多初学者会犯的错误)。
- 不需要 openjfx JavaFX SDK 下载(因为 JavaFX 模块依赖项是通过 maven 获取的)。
- 不需要手动设置 VM 参数到 运行 应用程序(因为适当的模块语句在 module-info.java 文件而不是 VM 命令行中)。
- 允许直接从 IDE.
执行和调试 JavaFX 应用程序
- 包括 openjfx maven 插件。
- 如果需要,您可以忽略它或从生成的项目文件中删除它。
关于 openjfx-maven 插件的一些想法:
- 对于大多数开发,我认为您不需要使用它。
- 如果您不需要它,您可以将它从您的项目中删除。
- openjfx maven 插件不是执行应用程序所必需的
- 尽管如果您真的愿意,也可以使用它,但据我所知,与在 IDE 中直接执行相比,它没有任何优势。
- openjfx maven 插件可用于构建基于 jlink 的分发,如果您希望这样做的话。
- openjfx maven 插件无法使用
jpackage
打包您的应用程序,至少目前是这样:
- 如果这是您想要做的事情,请调查 JPackageScriptFX, the ackman maven jpackage plugin or the badass jlink or runtime plugins,或使用一些替代工具,例如直接调用 jpackage。
先前的答案
先前回答中的一些信息对于理解 Java 平台模块化和 JavaFX 的背景信息仍然有用。
快速总结,你可以做:
- 像 José 的回答一样,通过
--module-path
和 --add-modules
包含 JavaFX 模块。
或
- 将 JavaFX 库添加到项目后(手动或通过 maven/gradle 导入),添加与此答案中指定的文件类似的
module-info.java
文件。 (请注意,此解决方案使您的应用程序模块化,因此如果您使用其他库,您还需要添加语句以在 module-info.java
文件中要求它们的模块)。
此回答是对何塞回答的补充。
情况是这样的:
- 您使用的是最新的 Java 版本,例如13.
- 您有一个 JavaFX 应用程序作为 Maven 项目。
- 在您的 Maven 项目中,您已根据 Jose 的回答配置了 JavaFX 插件和 JavaFX 依赖项设置。
- 您转到扩展应用程序的主要 class 的源代码,右键单击它并尝试 运行 它。
- 您在尝试启动应用程序时收到涉及“未命名模块”的
IllegalAccessError
。
在尝试 运行 来自 Intellij Idea 的 JavaFX 应用程序时生成 IllegalAccessError
的堆栈跟踪摘录:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.lang.IllegalAccessError: class com.sun.javafx.fxml.FXMLLoaderHelper (in unnamed module @0x45069d0e) cannot access class com.sun.javafx.util.Utils (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.util to unnamed module @0x45069d0e
at com.sun.javafx.fxml.FXMLLoaderHelper.<clinit>(FXMLLoaderHelper.java:38)
at javafx.fxml.FXMLLoader.<clinit>(FXMLLoader.java:2056)
at org.jewelsea.demo.javafx.springboot.Main.start(Main.java:13)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1(LauncherImpl.java:846)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
Exception running application org.jewelsea.demo.javafx.springboot.Main
好的,现在你有点卡住了,不知道发生了什么。
实际情况是这样的:
- Maven 已成功为您的应用程序下载 JavaFX 依赖项,因此您无需单独下载依赖项或安装 JavaFX SDK 或模块分发或类似的东西。
- Idea 已成功将模块作为依赖项导入到您的项目中,因此一切编译正常,所有代码完成,一切正常。
所以看起来一切都应该没问题。但是,当您 运行 您的应用程序时, JavaFX 模块中的代码在尝试使用反射来实例化您的应用程序实例时失败 class (当您调用启动时)和您的 FXML controller classes(加载 FXML 时)。如果没有一些帮助,这种反射的使用在某些情况下可能会失败,从而产生晦涩难懂的 IllegalAccessError
。这是由于 Java 模块系统安全功能不允许其他模块的代码在您的 classes 上使用反射,除非您明确允许(以及 JavaFX 应用程序启动器和FXMLLoader 都需要在其当前实现中进行反射才能使其正常运行)。
这就是这个问题的一些其他答案,参考 module-info.java
,进入画面。
那么让我们参加 Java 个模块的速成课程:
关键部分是这样的:
4.9. Opens
If we need to allow reflection of private types, but we don't want all
of our code exposed, we can use the opens directive to expose specific
packages.
But remember, this will open the package up to the entire world, so
make sure that is what you want:
module my.module { opens com.my.package; }
所以,也许你不想向全世界公开你的包裹,那么你可以这样做:
4.10. Opens … To
Okay, so reflection is great sometimes, but we still want as much security as we can get from encapsulation. We can selectively open our packages to a pre-approved list of modules, in this case, using the opens…to the directive:
module my.module {
opens com.my.package to moduleOne, moduleTwo, etc.;
}
因此,您最终创建了一个 src/main/java/module-info.java class,如下所示:
module org.jewelsea.demo.javafx.springboot {
requires javafx.fxml;
requires javafx.controls;
requires javafx.graphics;
opens org.jewelsea.demo.javafx.springboot to javafx.graphics,javafx.fxml;
}
其中 org.jewelsea.demo.javafx.springboot
是包的名称,其中包含 JavaFX 应用程序 class 和 JavaFX 控制器 classes(将其替换为适合您的应用程序的包名称)。这告诉 Java 运行 时间 class 中的 javafx.graphics
和 javafx.fxml
可以在 class 中调用反射你的 org.jewelsea.demo.javafx.springboot
包裹。完成此操作后,应用程序已编译并重新运行 一切正常,JavaFX 使用反射生成的 IllegalAccessError
将不再发生。
但是如果你不想创建一个模块-info.java文件怎么办
如果不是直接使用 IDE 顶部工具栏中的 运行 按钮来 运行 您的应用程序 class,而是:
- 去了IDE那边的Mavenwindow。
- 选择 JavaFX maven 插件目标
javafx.run
。
- 右键单击它并选择
Run Maven Build
或 Debug...
。
然后应用程序将 运行 没有 module-info.java
文件。我想这是因为 maven 插件足够智能,可以动态包含某种设置,即使没有 module-info.java
文件,也可以让应用程序反映在 JavaFX classes 上,虽然我不知道这是怎么实现的。
要将该设置转移到顶部工具栏中的 运行 按钮,请右键单击 javafx.run
Maven 目标并为目标选择 Create Run/Debug Configuration
选项。然后你可以从顶部的工具栏中选择 运行 来执行 Maven 目标。
可以在
找到很好的解释
https://edencoding.com/runtime-components-error/
包括
为您的模块提供反射访问
授予其他人访问您的模块的权限
总的来说,我们需要添加到上述答案中,将 exports 添加到您的模块定义
module my.project {
requires javafx.fxml;
requires javafx.controls;
opens my.project to javafx.graphics;
exports my.project;
}
现在是 2021 年,JetBrains 更新了他们的 IDE。关于此错误信息的其他问题已关闭并指向此处。
Error: JavaFX runtime components are missing, and are required to run this application
如果您已执行这些答案中的所有其他步骤(例如,库、--module-path
、--add-modules
、版本匹配 JDK 和 JavaFX),您仍然会看到此编译错误,确保你的 run/compile 配置有 --module-path
和 --add-modules
作为 VM Options
而不是 Program Arguments
in IntelliJ.
- 打开
Run/Debug Configurations
- 打开
Modify Options
下拉菜单
- 点击
Add VM Options
添加VM选项,(在运行配置中),这一行:
--module-path yourpathwheresdkislocated/lib --add-modules=javafx.controls,javafx.fxml
如果你想从终端运行你的 jar 应用程序,把这个
java --module-path yourpathwheresdkislocated/lib --add-modules=javafx.controls,javafx.fxml -jar YourJar.jar
我无法让 IntellJ 识别 JavaFX 包。使用 OpenJDK 11 的新 JavaFX 项目,在尝试构建项目时,IntelliJ 无法识别 JavaFX 包。
我已经从 Maven 存储库导入 openjfx:javafx-base-11
。
我查看了其他问题,解决方案似乎包括检查字节码是否处于正确级别(我的是)以及项目语言是否正确(我的是)。
有人有什么想法吗?
编辑:
错误:
如评论中所述,Starting Guide 是从 Java 11 和 JavaFX 11 开始的地方。
像以前一样工作的关键 Java11 是理解:
- JavaFX 11 不再是 JDK 的一部分
- 您可以以不同的方式获得它,作为 SDK 或作为 常规依赖项 (maven/gradle).
- 即使您的项目不是模块化的,您也需要将其包含到项目的模块路径中。
Java外汇项目
如果您在 IntelliJ 中创建常规 JavaFX 默认项目(没有 Maven 或 Gradle),我建议您从 here 下载 SDK。请注意,也有 jmod,但对于非模块化项目,首选 SDK。
这些是 运行 默认项目的简单步骤:
- 创建一个 JavaFX 项目
- 设置JDK11(指向你本地的Java11版本)
- 添加 JavaFX 11 SDK 作为库。 URL 可能类似于
/Users/<user>/Downloads/javafx-sdk-11/lib/
。执行此操作后,您会注意到 JavaFX 类 现在可以在编辑器中识别。
在你运行默认项目之前,你只需要将这些添加到VM选项:
--module-path /Users/<user>/Downloads/javafx-sdk-11/lib --add-modules=javafx.controls,javafx.fxml
运行
Maven
如果您使用 Maven 构建项目,请按照以下步骤操作:
- 使用 JavaFX 原型创建 Maven 项目
- 设置JDK11(指向你本地的Java11版本)
添加 JavaFX 11 依赖项。
<dependencies> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-controls</artifactId> <version>11</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-fxml</artifactId> <version>11</version> </dependency> </dependencies>
执行此操作后,您会注意到 JavaFX 类 现在可以在编辑器中识别。
您会注意到 Maven 为您管理所需的依赖项:它会为 javafx.controls 添加 javafx.base 和 javafx.graphics,但最重要的是,它会添加所需的 [=76] =]classifier 基于你的平台。就我而言,Mac.
这就是为什么你的罐子 org.openjfx:javafx-controls:11
是空的,因为存在三种可能的分类器(windows、linux 和 mac 平台),其中包含所有 类 和本机实现。
如果您仍想转到 .m2 存储库并从那里手动获取依赖项,请确保选择正确的(例如 .m2/repository/org/openjfx/javafx-controls/11/javafx-controls-11-mac.jar
)
用 here.
中的插件替换默认的 maven 插件
运行
mvn compile javafx:run
,应该可以。
Gradle 项目也有类似的工作方式,详见 here。
编辑
提到的入门指南包含更新的 documentation 和 IntelliJ 示例项目:
JavaFX 11 没有 Maven/Gradle,参见 non-modular sample or modular sample 个项目。
JavaFX 11 与 Maven,参见 non-modular sample or modular sample 个项目。
JavaFX 11 与 Gradle,参见 non-modular sample or modular sample 个项目。
JavaFX 不再是 JDK 11 的一部分的问题。 以下解决方案适用于 IntelliJ(尚未尝试使用 NetBeans):
添加 JavaFX 全局库作为依赖:
设置 -> 项目结构 -> 模块。在模块中转到 Dependencies 选项卡,并点击添加“+”号 -> Library -> Java-> 从列表中选择 JavaFX 并点击添加所选项,然后点击应用设置。
右键单击 JavaFX 项目中的源文件 (src),然后新建一个 模块-info.java 文件。在文件中写入以下代码:
module YourProjectName { requires javafx.fxml; requires javafx.controls; requires javafx.graphics; opens sample; }
这 2 个步骤将解决您使用 JavaFX 的所有问题,我向您保证。
参考:The Learn Programming 频道制作了一个 You Tube 教程,将在 5 分钟内解释上述所有细节。我还建议观看它来解决您的问题: https://www.youtube.com/watch?v=WtOgoomDewo
None 对我有用。我花了太多时间来清除出现的其他错误。我发现这是最简单也是最好的方法。
This works for getting JavaFx on Jdk 11, 12 & on OpenJdk12 too!
- 该视频向您展示了 JavaFx Sdk 下载
- 如何设置为全局库
- 设置模块-info.java(我更喜欢最下面的那个)
module thisIsTheNameOfYourProject {
requires javafx.fxml;
requires javafx.controls;
requires javafx.graphics;
opens sample;
}
整个过程只花了我 5 分钟 !!!
2020 年 12 月 14 日更新
Intellij 已为 Idea 创建了 new JavaFX project wizard。
我强烈推荐,如果您在使JavaFX项目工作时遇到问题,那么使用新的 JavaFX 项目向导 到:
- 使用向导创建一个新项目。
- 测试新项目是否有效。
- 将旧项目中的相关代码复制到新项目中。
新项目向导非常简单易用,可以在不到一分钟的时间内启动并运行Ning 正常工作的 JavaFX 项目。
向导生成的项目具有以下特点:
- 小型应用程序的简单工作示例代码。
- 使用 JavaFX 图形、控件、fxml。
- 配置 maven 或 gradle 项目以使用 JavaFX,并为基本开发提供适当的 maven 工件依赖项。
- 使用最近的、合理更新的 JavaFX 模块,具有一致的版本(这是许多初学者通常不会做的事情)。
- 添加模块-info.java 文件,适用于基于 FXML 的 JavaFX 应用程序(如果您不使用 FXML 也可以)。
- 演示将 FXML 文件放在资源目录中,并在 运行 时将其作为资源查找(这是很多很多初学者都会犯的错误)。
- 正确地将 Controller class 与 Application class 分开(这也是很多初学者会犯的错误)。
- 演示如何正确使用基于 FXML 文件中的 id 的 @FXML 注入(这也是很多初学者会犯的错误)。
- 不需要 openjfx JavaFX SDK 下载(因为 JavaFX 模块依赖项是通过 maven 获取的)。
- 不需要手动设置 VM 参数到 运行 应用程序(因为适当的模块语句在 module-info.java 文件而不是 VM 命令行中)。
- 允许直接从 IDE. 执行和调试 JavaFX 应用程序
- 包括 openjfx maven 插件。
- 如果需要,您可以忽略它或从生成的项目文件中删除它。
关于 openjfx-maven 插件的一些想法:
- 对于大多数开发,我认为您不需要使用它。
- 如果您不需要它,您可以将它从您的项目中删除。
- openjfx maven 插件不是执行应用程序所必需的
- 尽管如果您真的愿意,也可以使用它,但据我所知,与在 IDE 中直接执行相比,它没有任何优势。
- openjfx maven 插件可用于构建基于 jlink 的分发,如果您希望这样做的话。
- openjfx maven 插件无法使用
jpackage
打包您的应用程序,至少目前是这样:- 如果这是您想要做的事情,请调查 JPackageScriptFX, the ackman maven jpackage plugin or the badass jlink or runtime plugins,或使用一些替代工具,例如直接调用 jpackage。
先前的答案
先前回答中的一些信息对于理解 Java 平台模块化和 JavaFX 的背景信息仍然有用。
快速总结,你可以做:
- 像 José 的回答一样,通过
--module-path
和--add-modules
包含 JavaFX 模块。
或
- 将 JavaFX 库添加到项目后(手动或通过 maven/gradle 导入),添加与此答案中指定的文件类似的
module-info.java
文件。 (请注意,此解决方案使您的应用程序模块化,因此如果您使用其他库,您还需要添加语句以在module-info.java
文件中要求它们的模块)。
此回答是对何塞回答的补充。
情况是这样的:
- 您使用的是最新的 Java 版本,例如13.
- 您有一个 JavaFX 应用程序作为 Maven 项目。
- 在您的 Maven 项目中,您已根据 Jose 的回答配置了 JavaFX 插件和 JavaFX 依赖项设置。
- 您转到扩展应用程序的主要 class 的源代码,右键单击它并尝试 运行 它。
- 您在尝试启动应用程序时收到涉及“未命名模块”的
IllegalAccessError
。
在尝试 运行 来自 Intellij Idea 的 JavaFX 应用程序时生成 IllegalAccessError
的堆栈跟踪摘录:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.lang.IllegalAccessError: class com.sun.javafx.fxml.FXMLLoaderHelper (in unnamed module @0x45069d0e) cannot access class com.sun.javafx.util.Utils (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.util to unnamed module @0x45069d0e
at com.sun.javafx.fxml.FXMLLoaderHelper.<clinit>(FXMLLoaderHelper.java:38)
at javafx.fxml.FXMLLoader.<clinit>(FXMLLoader.java:2056)
at org.jewelsea.demo.javafx.springboot.Main.start(Main.java:13)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1(LauncherImpl.java:846)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
Exception running application org.jewelsea.demo.javafx.springboot.Main
好的,现在你有点卡住了,不知道发生了什么。
实际情况是这样的:
- Maven 已成功为您的应用程序下载 JavaFX 依赖项,因此您无需单独下载依赖项或安装 JavaFX SDK 或模块分发或类似的东西。
- Idea 已成功将模块作为依赖项导入到您的项目中,因此一切编译正常,所有代码完成,一切正常。
所以看起来一切都应该没问题。但是,当您 运行 您的应用程序时, JavaFX 模块中的代码在尝试使用反射来实例化您的应用程序实例时失败 class (当您调用启动时)和您的 FXML controller classes(加载 FXML 时)。如果没有一些帮助,这种反射的使用在某些情况下可能会失败,从而产生晦涩难懂的 IllegalAccessError
。这是由于 Java 模块系统安全功能不允许其他模块的代码在您的 classes 上使用反射,除非您明确允许(以及 JavaFX 应用程序启动器和FXMLLoader 都需要在其当前实现中进行反射才能使其正常运行)。
这就是这个问题的一些其他答案,参考 module-info.java
,进入画面。
那么让我们参加 Java 个模块的速成课程:
关键部分是这样的:
4.9. Opens
If we need to allow reflection of private types, but we don't want all of our code exposed, we can use the opens directive to expose specific packages.
But remember, this will open the package up to the entire world, so make sure that is what you want:
module my.module { opens com.my.package; }
所以,也许你不想向全世界公开你的包裹,那么你可以这样做:
4.10. Opens … To
Okay, so reflection is great sometimes, but we still want as much security as we can get from encapsulation. We can selectively open our packages to a pre-approved list of modules, in this case, using the opens…to the directive:
module my.module { opens com.my.package to moduleOne, moduleTwo, etc.; }
因此,您最终创建了一个 src/main/java/module-info.java class,如下所示:
module org.jewelsea.demo.javafx.springboot {
requires javafx.fxml;
requires javafx.controls;
requires javafx.graphics;
opens org.jewelsea.demo.javafx.springboot to javafx.graphics,javafx.fxml;
}
其中 org.jewelsea.demo.javafx.springboot
是包的名称,其中包含 JavaFX 应用程序 class 和 JavaFX 控制器 classes(将其替换为适合您的应用程序的包名称)。这告诉 Java 运行 时间 class 中的 javafx.graphics
和 javafx.fxml
可以在 class 中调用反射你的 org.jewelsea.demo.javafx.springboot
包裹。完成此操作后,应用程序已编译并重新运行 一切正常,JavaFX 使用反射生成的 IllegalAccessError
将不再发生。
但是如果你不想创建一个模块-info.java文件怎么办
如果不是直接使用 IDE 顶部工具栏中的 运行 按钮来 运行 您的应用程序 class,而是:
- 去了IDE那边的Mavenwindow。
- 选择 JavaFX maven 插件目标
javafx.run
。 - 右键单击它并选择
Run Maven Build
或Debug...
。
然后应用程序将 运行 没有 module-info.java
文件。我想这是因为 maven 插件足够智能,可以动态包含某种设置,即使没有 module-info.java
文件,也可以让应用程序反映在 JavaFX classes 上,虽然我不知道这是怎么实现的。
要将该设置转移到顶部工具栏中的 运行 按钮,请右键单击 javafx.run
Maven 目标并为目标选择 Create Run/Debug Configuration
选项。然后你可以从顶部的工具栏中选择 运行 来执行 Maven 目标。
可以在
找到很好的解释https://edencoding.com/runtime-components-error/
包括
为您的模块提供反射访问
授予其他人访问您的模块的权限
总的来说,我们需要添加到上述答案中,将 exports 添加到您的模块定义
module my.project {
requires javafx.fxml;
requires javafx.controls;
opens my.project to javafx.graphics;
exports my.project;
}
现在是 2021 年,JetBrains 更新了他们的 IDE。关于此错误信息的其他问题已关闭并指向此处。
Error: JavaFX runtime components are missing, and are required to run this application
如果您已执行这些答案中的所有其他步骤(例如,库、--module-path
、--add-modules
、版本匹配 JDK 和 JavaFX),您仍然会看到此编译错误,确保你的 run/compile 配置有 --module-path
和 --add-modules
作为 VM Options
而不是 Program Arguments
in IntelliJ.
- 打开
Run/Debug Configurations
- 打开
Modify Options
下拉菜单 - 点击
Add VM Options
添加VM选项,(在运行配置中),这一行:
--module-path yourpathwheresdkislocated/lib --add-modules=javafx.controls,javafx.fxml
如果你想从终端运行你的 jar 应用程序,把这个
java --module-path yourpathwheresdkislocated/lib --add-modules=javafx.controls,javafx.fxml -jar YourJar.jar