迁移到 JDK 11 + JavaFX 11 给出 RuntimeException
Posted
技术标签:
【中文标题】迁移到 JDK 11 + JavaFX 11 给出 RuntimeException【英文标题】:Migration to JDK 11 + JavaFX 11 giving RuntimeException 【发布时间】:2019-03-29 20:29:26 【问题描述】:我有一个基于 Java 8 + JavaFX 的应用程序,我想迁移到 Java 11。其基本目标是为网络上的用户提供一个 .jar,以便他们可以使用这个小应用程序。我使用 JavaFX 作为接口,使用 sqlite-jdbc 生成数据库。
我有我的 module-info.java,编译似乎没问题:没有错误。但是如果我运行该应用程序,就会出现这个错误:
Graphics Device initialization failed for : d3d, sw
Error initializing QuantumRenderer: no suitable pipeline found
java.lang.RuntimeException: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer.getInstance(QuantumRenderer.java:280)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.init(QuantumToolkit.java:222)
at javafx.graphics/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:260)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:409)
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:566)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:94)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:124)
at java.base/java.lang.Thread.run(Thread.java:834)
Exception in thread "main" 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:566)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: No toolkit found
at javafx.graphics/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:272)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:409)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
... 5 more
我的模块信息.java
module AutoGeneratorOpenData
requires javafx.base;
requires javafx.controls;
requires javafx.fxml;
requires javafx.graphics;
requires sqlite.jdbc;
requires java.sql;
requires java.desktop;
exports autogeneratoropendata;
我在 Windows 10 x64 位和 JavaFX Windows SDK(最新版本 11)上使用 Netbeans 9。我没有使用 Maven(但也许我必须?)。
有办法解决这个问题吗?
【问题讨论】:
你确定这是Java11吗?如:***.com/questions/21185156/… ...这个问题似乎经常出现。这也可能是应该运行 JavaFx 应用程序的操作系统的问题!所以这里不要关注 JVM 版本。除非应用程序在 Java8 的同一台机器上工作,但在 java11 上失败。 尝试使用-Dprism.verbose=true
运行,看看是否能提供有关问题的更多信息。这确实不是 JavaFX 11 特有的新问题,但它发生的原因有很多。
我遇到了同样的问题。有一个 JavaFX SDK 可供下载。在这个档案中有一个 bin 文件夹。在这个 bin 文件夹中有很多需要的 dll 和其他文件。在 Java 8 中,它们自动位于 bin 文件夹中。这些附加文件必须位于应用程序可以找到它们的路径上。
顺便问一下你用的是哪个罐子?如果我查看 Maven 存储库,就会发现特定于操作系统的 jar 中可能包含必要的本机库。我不敢相信您需要手动设置 natives 目录,没有任何文档提及需要这样做。
@GhostCat 确实是 Java 11,我确定(在我的项目属性、源代码和库中选择了 JDK 11)。
【参考方案1】:
所以,缺少一些库。
在 Windows 上,javafx-sdk-11/bin 中缺少的 DLL 至少为 prism_d3d.dll、prism_sw.dll、javafx_font.dll、glass.dll;您可以将所有内容放入 jdk 目录 C:\Program Files\Java\jdk[...]\bin
(这不是最好的解决方案),或者放入 jlink 目录中以用于自定义 JRE,在 。 p>[...]\jlink\bin\
内
在 Linux 上,javafx-sdk-11/lib 中缺少的 .so 至少是 libprism_es2.os、libprism_sw.so、libglass.so、libglassgtk3.so(和 libglassgtk2.so)。所以对于旧配置可能也是如此),libjavafx_font.so,libjavafx_font_freetype.so,libjavafx_font_pango.so;例如,您可以将所有内容放入/usr/lib/jvm/java-11[...]/lib
(这不是最佳解决方案),或者放入 p>[...]/jlink/lib
内的自定义 JRE 的 jlink 目录。
在 Mac 上,jav javafx-sdk-11/lib 中缺少的 .dylib 必须是(我想!)libprism_es2.dylib、libprism_sw.dylib、libglass.dylib、libjavafx_font。 dylib [确认]。
要使用 jlink,您应该使用 jmods - 无需使用库文件。
而我的 module-info.java 并不完整:
module AutoGeneratorOpenData
requires sqlite.jdbc;
requires javafx.controls;
requires javafx.graphics;
requires java.sql;
requires java.desktop;
requires javafx.fxml;
requires javafx.base;
exports autogeneratoropendata;
exports autogeneratoropendata.controller;
exports autogeneratoropendata.model;
exports autogeneratoropendata.util;
opens autogeneratoropendata.controller;
现在它正在工作。
【讨论】:
当你说原生库丢失时,你是从哪里得到它们的?如果您使用jlink
,则不必使用JavaFX SDK,而是使用JavaFX jmods
。看到这个answer。
@JoséPereda 当我在 Windows 上启动我的 .bat 时,我得到:“图形设备初始化失败:d3d,sw”对应于 prism_d3d.dll、prism_sw.dll(确实来自 JavaFX SDK) ;然后再次出现关于 javafx_font 和 java.library.path 中没有玻璃的错误。如果我把所有的 DLL,jlink 工作。在 Linux 上,在我的终端上,我在启动 .sh 时遇到了同样的问题,我得到了:'图形设备初始化失败:es2,sw',字体相同,'java 中没有 glassgtk3。库.路径'。如果所有 .so 文件都在 lib 目录中,则脚本有效。但也许我错了?
你检查过推荐的答案吗?如果您使用 jlink,则需要 JavaFX jmods。这些包含给定平台的类和本机库。
@JoséPereda 确实与 jmods 配合得更好;我会编辑我的评论,谢谢。顺便说一句,对不起,但我真的不明白你如何以及在哪里创建你的变量(它是一个环境变量吗?)'export PATH_TO_FX_JMOD=/path/to/javafx-jmods-11/' - 你能更准确吗?
环境变量是为方便起见,当然可以用硬编码的路径。如果你在终端上,你可以输入它,或者你可以将它添加到你的 Windows 设置中,就像你对 JAVA_HOME
所做的那样。【参考方案2】:
在 Windows 上,更新了 PATH 变量以包含 javafx-sdk-11/bin。
【讨论】:
【参考方案3】:还应注意,如果您使用的是 Eclipse(我知道您不是在这种情况下)和 Maven,为特定于平台的 javafx-graphics 库(win、mac、linux)添加依赖项将导致此问题,如果您尝试通过 Maven 构建。我不完全确定为什么。
在我刚刚删除 pom 中的平台相关依赖项并最终运行之前,我正试图在目标中做一个干净的 javafx:run。
【讨论】:
【参考方案4】:你也可以使用:
System.setProperty("java.library.path", "path/to/javafx-sdk-11.0.x/lib");
path/to/javafx-sdk-11.0.x/lib
是 JavaFX 的 lib(或对于 Windows,bin
)目录的路径。
请注意,如果 JavaFX 应用程序是从辅助类启动的,则此技术将起作用。从 JDK9 开始,直接从它自己的类启动 JavaFX 应用程序需要模块系统(例如module-info.java
等)。
【讨论】:
这不是真的。您不需要任何 module-info.java 即可启动 JavaFX9+ 程序。我什至使用 JavaFX 15 EA 并且从不使用模块信息。 我很想用这些信息改进答案。如何在不使用 JDK9+ 中的新模块系统的情况下直接启动 JavaFX 应用程序?你能详细说明一下吗?我问是因为我可以在使用 Java 8 时直接使用 - 例如 - IntelliJ Run 按钮启动应用程序,但不能更高。 看看我的公开仓库:github.com/mipastgt/JFXToolsAndDemos 没有一个项目有 module-info.java。您也可以在这里查看示例:github.com/openjfx/samples#CLI-Non-Modular-Samples 谢谢。我看过hellofx,它也使用一个单独的类来启动Application
。 github.com/openjfx/samples/blob/master/CommandLine/Non-modular/…。我查看了JFXToolsAndDemos
,但它包含几个项目。我看到的第一个没有扩展 Application
所以也许可以提供一个确切的例子。
自述文件准确地告诉您如何运行每个模块。这为您提供了所有主要课程。看看以 ...Demo 结尾的模块和类。【参考方案5】:
请使用最新的 JavaFX 版本,已经解决了许多错误
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>15</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>15</version>
</dependency>
【讨论】:
JFX 15 适用于 JDK 15 @codeflush.dev: 不,我在 JDK 8 中使用它以上是关于迁移到 JDK 11 + JavaFX 11 给出 RuntimeException的主要内容,如果未能解决你的问题,请参考以下文章
OpenJDK11+JavaFX+Maven环境搭建及最小化案例