Java 12 和 JavaFX 12 - 创建可运行的 jar 和自定义 JRE

标签 java eclipse javafx javafx-11

我正在尝试调整我的程序以在 Java 12 上运行。它目前在 Java 8 上运行并具有一些 JavaFX 组件(一些对话框)。它不是模块化的。我的 IDE 是 Eclipse,JavaFX jar 文件作为用户库包含在构建路径中。我想生成一个可运行的 jar 并将 javafx 文件捆绑在其中或将它们添加到自定义 JRE,以便我可以分发它,而不需要最终用户单独安装 Java12 或 JavaFX。

首先,我想尝试一个简单的 HelloFX程序被修改为更类似于我的程序。

public class HelloFX2 {

    public HelloFX2() {
        startToolkit();

        // have to wait a second for the JavaFX thread to actually start, or else the Platform.runLater throws an exception
        try
        {
            Thread.sleep(1000);
        }
        catch(InterruptedException ex)
        {
            Thread.currentThread().interrupt();
        }

        // create the scene and display
        Platform.runLater(() -> {
            Scene theScene = createTheScene();
            final Stage stage = new Stage();
            stage.setScene(theScene);
            stage.show();
        });

    }

    public Scene createTheScene() {
        String javaVersion = System.getProperty("java.version");
        String javafxVersion = System.getProperty("javafx.version");
        Label l = new Label("Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".");
        Scene scene = new Scene(new StackPane(l), 640, 480);
        return scene;
    }

    public void startToolkit () {
        // we can only create a Scene in a JavaFX thread
        SwingUtilities.invokeLater(() -> {

            // Initialize FX Toolkit, so that we can use the Java FX objects
            new JFXPanel();
        });
    }

}

我还使用了 Main 类来运行,按照 this suggestion 。我认为在我的情况下不需要它,因为 HelloFX2 没有扩展 Application,但这又更接近我的实际程序。

public class Main2 {
    public static void main(String[] args) {
        HelloFX2 theApp = new HelloFX2();
    }
}

程序在Eclipse中运行良好。我使用“Extract Libraries”选项导出为可运行的 JAR 文件,然后使用 jdepsjlink 创建自定义 JRE:

D:\Work\Java12>"C:\Program Files\Java\jdk-12.0.1\bin\jdeps" --ignore-missing-deps --print-module-deps HelloFX2.jar
java.base,java.desktop

D:\Work\Java12>"C:\Program Files\Java\jdk-12.0.1\bin\jlink" --no-header-files --no-man-pages  --add-modules java.base,java.desktop --output java-runtime

但是当我尝试运行它时,出现此错误:

D:\Work\Java12>"java-runtime\bin\java" -jar HelloFX2.jar
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 com.sun.javafx.tk.quantum.QuantumRenderer.getInstance(QuantumRenderer.java:280)
        at com.sun.javafx.tk.quantum.QuantumToolkit.init(QuantumToolkit.java:243)
        at com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:260)
        at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
        at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
        at javafx.embed.swing.JFXPanel.lambda$initFx$1(JFXPanel.java:224)
        at java.base/java.lang.Thread.run(Thread.java:835)
Caused by: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found
        at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:94)
        at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:124)
        ... 1 more
Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: No toolkit found
        at com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:272)
        at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
        at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
        at javafx.embed.swing.JFXPanel.lambda$initFx$1(JFXPanel.java:224)
        at java.base/java.lang.Thread.run(Thread.java:835)

当您不将 --module-path 开关添加到命令行时,这与原始 HelloFX 程序发生的错误相同,但我不需要它,因为我不扩展 Application .

没有找到JavaFX吗? JavaFX 类文件都包含在 jar 中,但我不知道如何指向它们。

最佳答案

使用 JavaFX SDK,有一个 lib 文件夹,其中包含 javafx.base.jarjavafx.controls.jar 等 jar 文件,但也有一些原生库,例如 libglass.so (Linux)、libglass.dylib(Mac)。在 Windows 上, native dll(例如 glass.dll)位于 bin 文件夹中。

将这些类打包到 fat jar 中时,您还必须考虑所需的 native 库。

这意味着您必须打包 javafx.graphics 的 native 库,但如果您不使用 webkit 库(会增加大约 80 MB),则不需要包含javafx.web 模块。

另请注意,这些库是特定于平台的(甚至是 jar)。如果您想将 jar 分发到其他平台,您还可以打包这些平台中的类和 native 库,只需下载它们的 SDK 即可。

所有这些都在https://openjfx.io/openjfx-docs/#modular中有详细解释。 ,非模块化项目 - 命令行部分。

对于模块化项目,推荐使用jlink工具。在这两种情况下,使用构建工具(Gradle/Maven)确实有助于处理 JavaFX 依赖项:您不需要 JavaFX SDK,因为您将从 Maven Central 检索依赖项,并且这些工具已经将 native 库与它们捆绑在一起。再次强调,值得阅读全文 https://openjfx.io/openjfx-docs/#modular文档。

关于Java 12 和 JavaFX 12 - 创建可运行的 jar 和自定义 JRE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56771832/

相关文章:

java - 在测试方法中模拟类

JavaFx 图表在悬停时突出显示整条曲线

javafx - 如何清除 DatePicker

java - 什么使 java 中的枚举不可实例化?

java - 当 MANIFEST.MF 中列出该类时,为什么我的 jar 会生成 NoClassDefFoundError?

java - Stack.peek() 比较返回错误结果 -1024

java - Eclipse:在文本编辑器中使用UTF-8编码使字符串无法正常工作,我该如何解决这个问题?

java - JUnit Eclipse - 成功时显示堆栈跟踪

java - 隐藏 "cannot be resolved"错误

java - 如何在JAVAFX中自定义组合框