使用 Quarkus 或 Springboot 和 JavaFx 的本机可执行文件
Native Executable with Quarkus or Springboot and JavaFx
我正在尝试为使用 Quarkus 和 JavaFx 的应用构建本机可执行文件。
我设法实现这一目标的唯一方法是将大量 javaFx 类 标记为 --initialize-at-运行-time,但这会导致在尝试启动应用程序时失败以下消息:
java.lang.ClassNotFoundException: com.sun.javafx.tk.quantum.QuantumToolkit
at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:71)
at java.lang.Class.forName(DynamicHub.java:1319)
at com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:251)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:195)
at java.lang.Thread.run(Thread.java:829)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:567)
at com.oracle.svm.core.windows.WindowsJavaThreads.osThreadStartRoutine(WindowsJavaThreads.java:138)
2021-09-09 16:02:21,173 ERROR [io.qua.run.Application] (main) Failed to start application (with profile prod): java.lang.RuntimeException: No toolkit found
at com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:273)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:195)
at java.lang.Thread.run(Thread.java:829)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:567)
at
com.oracle.svm.core.windows.WindowsJavaThreads.osThreadStartRoutine(WindowsJavaThreads.java:138)
我想我需要在构建之前添加 javafx 模块,但不知道如何从 Maven 实现它。如果有人可以帮助我,我将不胜感激。提前致谢。
PS:如果有人知道使用 springboot 的替代解决方案,请分享 :)
更新: 使用 SpringBoot 测试,使用 spring-native 和 gluonfx 也失败。
制作了一个最小的可复制文件,您可以从以下位置下载:
https://github.com/ikaro143/JavaFx-SpringBoot-example/tree/master
maven 命令应该在 VisualStudio Native Tools 命令提示中执行
要使用 spring 插件构建,请使用:mvn clean package -Pnative
要使用 gluonfx 构建,请使用:mvn clean gluonfx:build -Pnative-gluonfx
在这两种情况下都构建了 .exe,但是 none 两者都有效。
从控制台执行 spring 编译会抛出此 stackTrace(执行 gluon build 不会提供任何反馈,但都不起作用):
Exception in thread "main" java.lang.RuntimeException: Application launch error
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:202)
at java.lang.Thread.run(Thread.java:829)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:567)
at com.oracle.svm.core.windows.WindowsJavaThreads.osThreadStartRoutine(WindowsJavaThreads.java:138)
Caused by: java.lang.AssertionError: java.lang.ClassNotFoundException: javafx.scene.image.Image
at com.sun.javafx.util.Utils.forceInit(Utils.java:868)
at com.sun.javafx.tk.Toolkit.<clinit>(Toolkit.java:945)
at com.oracle.svm.core.classinitialization.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:375)
at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:295)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:286)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:160)
at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:195)
... 3 more
Caused by: java.lang.ClassNotFoundException: javafx.scene.image.Image
at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:71)
at java.lang.Class.forName(DynamicHub.java:1319)
at com.sun.javafx.util.Utils.forceInit(Utils.java:865)
... 11 more
更新: 共享 Quarkus + Jafavx 的最小可重现性
https://github.com/ikaro143/JavaFx-Quarkus-example
要使用 quarkus 插件构建,请使用:mvn clean package -Pnative
要使用 gluonfx 构建,请使用:mvn clean gluonfx:build -Pnative-gluonfx
Quarkus 方法在分析步骤失败。有几个错误如下:
analysis: 45,621.43 ms, 3.89 GB
Error: Unsupported features in 12 methods
Detailed message:
Error: Class initialization of com.sun.javafx.tk.quantum.PrismImageLoader2$AsyncImageLoader failed. Use the option --initialize-at-run-time=com.sun.javafx.tk.quantum.PrismImageLoader2$AsyncImageLoader to explicitly request delayed initialization of this class.
Original exception that caused the problem: java.lang.ExceptionInInitializerError
at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1042)
at jdk.unsupported/sun.misc.Unsafe.ensureClassInitialized(Unsafe.java:698)
at jdk.internal.vm.compiler/org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.ensureClassInitialized(GraalUnsafeAccess.java:77)
gluonfx 方法在设置步骤失败并出现以下模糊错误:
[com.quarkusjavafx.example.applauncher.cdiapplication:9740] classlist: 3,592.40 ms, 1.19 GB
[com.quarkusjavafx.example.applauncher.cdiapplication:9740] (cap): 3,086.44 ms, 1.19 GB
[com.quarkusjavafx.example.applauncher.cdiapplication:9740] setup: 6,095.10 ms, 1.19 GB
Fatal error:java.lang.NullPointerException
at java.base/java.io.Reader.<init>(Reader.java:167)
at java.base/java.io.InputStreamReader.<init>(InputStreamReader.java:72)
at io.quarkus.runtime.graal.ResourcesFeature.beforeAnalysis(ResourcesFeature.java:21)
at com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis(NativeImageGenerator.java:691)
at com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:71)
at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:691)
at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:532)
at com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:491)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:380)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:543)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:119)
at com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus.main(NativeImageGeneratorRunner.java:573)
[com.quarkusjavafx.example.applauncher.cdiapplication:9740] [total]: 9,723.35 ms, 1.19 GB
已更新 根据 José Pereda 的建议,我尝试将后端迁移到 Micronaut,并成功构建了本机映像。从 springboot 到 micronaut 的迁移非常容易。只需更改 pom 中的父级和基本依赖项。
原生镜像使用maven代码生成:
mvn clean gluonfx: build -Pnative-gluonfx
也许您需要先使用目标 gluonfx:runagent
来生成 运行.
所需的配置文件
根据我的经验,我遇到了一些依赖项问题,只有在构建完成后 运行 实现目标 gluonfx:nativerun
时才会注意到。然后调整代码。
我在这里留下一个最小的例子,以防有人需要它:
https://github.com/ikaro143/example-micronaut
PS: 确保您的主要 class 已注册反射。
我正在尝试为使用 Quarkus 和 JavaFx 的应用构建本机可执行文件。 我设法实现这一目标的唯一方法是将大量 javaFx 类 标记为 --initialize-at-运行-time,但这会导致在尝试启动应用程序时失败以下消息:
java.lang.ClassNotFoundException: com.sun.javafx.tk.quantum.QuantumToolkit
at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:71)
at java.lang.Class.forName(DynamicHub.java:1319)
at com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:251)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:195)
at java.lang.Thread.run(Thread.java:829)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:567)
at com.oracle.svm.core.windows.WindowsJavaThreads.osThreadStartRoutine(WindowsJavaThreads.java:138)
2021-09-09 16:02:21,173 ERROR [io.qua.run.Application] (main) Failed to start application (with profile prod): java.lang.RuntimeException: No toolkit found
at com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:273)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:195)
at java.lang.Thread.run(Thread.java:829)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:567)
at
com.oracle.svm.core.windows.WindowsJavaThreads.osThreadStartRoutine(WindowsJavaThreads.java:138)
我想我需要在构建之前添加 javafx 模块,但不知道如何从 Maven 实现它。如果有人可以帮助我,我将不胜感激。提前致谢。
PS:如果有人知道使用 springboot 的替代解决方案,请分享 :)
更新: 使用 SpringBoot 测试,使用 spring-native 和 gluonfx 也失败。
制作了一个最小的可复制文件,您可以从以下位置下载: https://github.com/ikaro143/JavaFx-SpringBoot-example/tree/master
maven 命令应该在 VisualStudio Native Tools 命令提示中执行
要使用 spring 插件构建,请使用:mvn clean package -Pnative
要使用 gluonfx 构建,请使用:mvn clean gluonfx:build -Pnative-gluonfx
在这两种情况下都构建了 .exe,但是 none 两者都有效。
从控制台执行 spring 编译会抛出此 stackTrace(执行 gluon build 不会提供任何反馈,但都不起作用):
Exception in thread "main" java.lang.RuntimeException: Application launch error
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:202)
at java.lang.Thread.run(Thread.java:829)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:567)
at com.oracle.svm.core.windows.WindowsJavaThreads.osThreadStartRoutine(WindowsJavaThreads.java:138)
Caused by: java.lang.AssertionError: java.lang.ClassNotFoundException: javafx.scene.image.Image
at com.sun.javafx.util.Utils.forceInit(Utils.java:868)
at com.sun.javafx.tk.Toolkit.<clinit>(Toolkit.java:945)
at com.oracle.svm.core.classinitialization.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:375)
at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:295)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:286)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:160)
at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:195)
... 3 more
Caused by: java.lang.ClassNotFoundException: javafx.scene.image.Image
at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:71)
at java.lang.Class.forName(DynamicHub.java:1319)
at com.sun.javafx.util.Utils.forceInit(Utils.java:865)
... 11 more
更新: 共享 Quarkus + Jafavx 的最小可重现性
https://github.com/ikaro143/JavaFx-Quarkus-example
要使用 quarkus 插件构建,请使用:mvn clean package -Pnative
要使用 gluonfx 构建,请使用:mvn clean gluonfx:build -Pnative-gluonfx
Quarkus 方法在分析步骤失败。有几个错误如下:
analysis: 45,621.43 ms, 3.89 GB
Error: Unsupported features in 12 methods
Detailed message:
Error: Class initialization of com.sun.javafx.tk.quantum.PrismImageLoader2$AsyncImageLoader failed. Use the option --initialize-at-run-time=com.sun.javafx.tk.quantum.PrismImageLoader2$AsyncImageLoader to explicitly request delayed initialization of this class.
Original exception that caused the problem: java.lang.ExceptionInInitializerError
at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1042)
at jdk.unsupported/sun.misc.Unsafe.ensureClassInitialized(Unsafe.java:698)
at jdk.internal.vm.compiler/org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.ensureClassInitialized(GraalUnsafeAccess.java:77)
gluonfx 方法在设置步骤失败并出现以下模糊错误:
[com.quarkusjavafx.example.applauncher.cdiapplication:9740] classlist: 3,592.40 ms, 1.19 GB
[com.quarkusjavafx.example.applauncher.cdiapplication:9740] (cap): 3,086.44 ms, 1.19 GB
[com.quarkusjavafx.example.applauncher.cdiapplication:9740] setup: 6,095.10 ms, 1.19 GB
Fatal error:java.lang.NullPointerException
at java.base/java.io.Reader.<init>(Reader.java:167)
at java.base/java.io.InputStreamReader.<init>(InputStreamReader.java:72)
at io.quarkus.runtime.graal.ResourcesFeature.beforeAnalysis(ResourcesFeature.java:21)
at com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis(NativeImageGenerator.java:691)
at com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:71)
at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:691)
at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:532)
at com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:491)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:380)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:543)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:119)
at com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus.main(NativeImageGeneratorRunner.java:573)
[com.quarkusjavafx.example.applauncher.cdiapplication:9740] [total]: 9,723.35 ms, 1.19 GB
已更新 根据 José Pereda 的建议,我尝试将后端迁移到 Micronaut,并成功构建了本机映像。从 springboot 到 micronaut 的迁移非常容易。只需更改 pom 中的父级和基本依赖项。
原生镜像使用maven代码生成:
mvn clean gluonfx: build -Pnative-gluonfx
也许您需要先使用目标 gluonfx:runagent
来生成 运行.
根据我的经验,我遇到了一些依赖项问题,只有在构建完成后 运行 实现目标 gluonfx:nativerun
时才会注意到。然后调整代码。
我在这里留下一个最小的例子,以防有人需要它: https://github.com/ikaro143/example-micronaut
PS: 确保您的主要 class 已注册反射。