从Maven使用JavaFX11构建可执行的JAR [英] Build executable JAR with JavaFX11 from maven
问题描述
我制作了一个使用Maven,JavaFX和一些其他依赖项的Java应用程序. 以前,构建可执行jar很容易,但是由于Java11是模块化的,并且不包含JavaFX,所以我无法构建可运行的jar.
I've made a Java app which uses Maven, JavaFX and some other dependencies. Before, it was easy to build an executable jar but since Java11 is modular and does not include JavaFX i just can't build a working one.
我已经尝试了很多事情,但是我不知道现在该怎么做.
I've already tried a lot of things but i don't know what i'm supposed to do now.
我的pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<verbose>true</verbose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<outputDirectory>out/</outputDirectory>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>fr.crosf32.fxtest.Entry</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
我尝试构建内部具有所有依赖项的工件,但是运行(java -jar)时出现错误:
I've tried to build artifact with all dependencies inside but i obtain an error when i run (java -jar ):
Exception in thread "Thread-0" java.lang.NoClassDefFoundError: javafx/application/Application
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:802)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:700)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:623)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at fr.crosf32.fxtest.SlimForest.lambda$new$0(SlimForest.java:26)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.ClassNotFoundException: javafx.application.Application
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 11 more
编辑
我尝试使用Jlink构建一个包含JavaFX的jar,但是当我尝试运行该应用程序时,我获得了:
I've tried to build a jar which contains JavaFX using Jlink but when i try to run the app i obtain :
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.launchApplication1(LauncherImpl.java:678)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:834)
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)
... 1 more
Exception in thread "Thread-0" 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.launchApplication1(LauncherImpl.java:678)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:834)
推荐答案
我也在创建可执行jar的过程中苦苦挣扎,但是这种解决方法对我来说很有效,我希望它也对您有用:
I struggled through the process of creating an executable jar as well, but this workaround is what worked for me, and I hope it works for you as well:
首先,我没有使用jar
插件,而是在pom.xml
中使用了shade
插件,该插件创建了一个胖罐"或超罐",其中包含您的类以及其中的所有依赖项罐子里这样,您的jar将包含在所有必需的javafx
软件包和类中.也就是说,如果您将这些添加到<dependencies>
部分:
First of all, instead of using the jar
plugin, I used the shade
plugin in pom.xml
, which creates a "fat jar" or "uber jar" that contains your classes and all of the dependencies within the jar. This way, your jar will be included with all the necessary javafx
packages and classes. That is, if you include these in the <dependencies>
section:
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>11</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
</dependency>
...或您需要的其他任何javafx
库,以便应用程序运行.
... or whatever else of the javafx
libraries you need in order for your application to run.
但是,仅这样做是行不通的.我假设您的主要课程Entry extends Application
?
Simply doing this does not work, however. I'm assuming that your main class Entry extends Application
?
我猜想jar
需要了解不会扩展Application的实际Main类,因此我刚刚创建了另一个名为SuperMain
的Main类( (只是一个临时名称)调用了我原来的主类,即Main
:
I'm guessing the jar
needs to know the actual Main class that does not extend Application, so I just created another Main class called SuperMain
(it was only a temporary name) that calls my original main class, which is Main
:
// package <your.package.name.here>
public class SuperMain {
public static void main(String[] args) {
Main.main(args);
}
}
而您的情况是Entry
.
所以在我的pom.xml中,我有一个名为shade
的插件,如下所示:
So in my pom.xml, I have a plugin called shade
that looks like this:
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>my.package.name.SuperMain</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
在执行mvn package
之后,应该有一个阴影"的jar.
and there should be a jar that's "shaded" after you execute mvn package
.
感谢这篇文章的答案: JavaFX 11 :使用Gradle创建一个jar文件
Thanks to the answer to this post: JavaFX 11 : Create a jar file with Gradle
希望这会有所帮助!
这篇关于从Maven使用JavaFX11构建可执行的JAR的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!