迁移到 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,在 [...]\jlink\bin\。 p>

在 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这不是最佳解决方案,或者放入 [...]/jlink/lib 内的自定义 JRE 的 jlink 目录。 p>

在 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:ru​​n。

【讨论】:

【参考方案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的主要内容,如果未能解决你的问题,请参考以下文章

使用 JDK 11+ 运行 JavaFX 应用程序

JavaFX:JDK 11+打包成exe

OpenJDK11+JavaFX+Maven环境搭建及最小化案例

如何安装JavaFX

在模块路径上使用 OpenJFX 11 JMODS 在 JDK 11 上运行 javafx 示例

将JVM从JDK11迁移到JDK16的问题