我们正在用Adopt JDK11和IntelliJ使用Gradle开发一个JavaFX11应用程序。最后,我们需要一个用于windows的EXE文件(该应用程序仅为windows设计)。在第一次尝试中,我们也使用了gradle中的launch4J,由于以下问题,我们也可以使用BAT文件,我们可以迁移到exe文件。
所以我们的主要目标和问题是,如何才能创建一个可执行的jar文件。
我们进行了几次尝试,结果各不相同,我们完全迷失了方向。
我们为测试目的制作了一个独立的应用程序:
package de.test;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch();
}
@Override
public void start(Stage primaryStage) throws Exception {
VBox vBox = new VBox();
Button button = new Button("Klick");
TextField textfield = new TextField();
TextArea area = new TextArea();
area.setMinHeight(300);
button.setOnAction(event -> area.setText(area.getText() + " -- Klick Version 1.0.8"));
vBox.getChildren().addAll(button, textfield,area);
primaryStage.setScene(new Scene(vBox));
primaryStage.setTitle("Test");
primaryStage.show();
}
}
肥罐
我们的第一次尝试是使用Gradle的javafx插件创建一个FAT-JAR,无论它有没有modules-info.java文件。这是我们的卷宗
plugins {
id 'java'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.8'
}
group 'de.test'
version '1.0.8'
sourceCompatibility = 11
javafx {
modules = ['javafx.controls']
}
mainClassName = 'de.test.Main'
jar {
manifest {
attributes 'Main-Class': mainClassName
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
repositories {
mavenLocal()
mavenCentral()
}
运行gradle clean jar之后,我们尝试使用以下命令java-jar applicationtest-1.0.8.jar执行jar,结果:
compile group: 'org.jboss.resteasy', name: 'resteasy-client', version: '4.3.0.Final'
compile "org.openjfx:javafx-graphics:11.0.2:win"
compile "org.openjfx:javafx-base:11.0.2:win"
compile "org.openjfx:javafx-controls:11.0.2:win"
compile "org.openjfx:javafx-fxml:11.0.2:win"
compile "org.openjfx:javafx-graphics:11.0.2:win"
module ApplicationTest.main {
requires javafx.controls;
exports de.test;
}
在调用gradle installDist时,我们使用了以下命令
cd build\install\applicationtest\lib java--add-modules“javafx.controls”--module-path。-jar applicationtest-1.0.8.jar
至少应用程序在此时启动,但布局被以下info消息破坏:
下一种方法是使用jlink和以下模块-info.java
module ApplicationTest.main {
requires javafx.controls;
requires javafx.graphics;
exports de.test;
}
我们需要将gradle文件扩展如下
plugins {
id 'java'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.8'
id 'org.beryx.jlink' version '2.10.4'
}
group 'de.test'
version '1.0.8'
sourceCompatibility = 11
mainClassName = 'de.test.Main'
javafx {
version = 11
modules = [ 'javafx.controls']
}
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
}
repositories {
mavenLocal()
mavenCentral()
}
当使用gradle jlink并执行cd build\image\bin\applicationtest.bat文件时,应用程序从布局开始。
dependencies {
compile "commons-io:commons-io:2.6"
compile "org.apache.logging.log4j:log4j-api:2.11.2"
compile "dom4j:dom4j:1.6.1"
compile "commons-lang:commons-lang:2.6"
compile "axis:axis:1.4"
compile "jaxen:jaxen:1.1.6"
compile "net.java.dev.jna:platform:3.5.2"
compile "org.apache.poi:poi:4.1.0"
compile "org.apache.poi:poi-scratchpad:4.1.0"
compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.4"
}
但是,当我添加其他依赖项时,我会得到不同类型的错误消息。我尝试单独使用每个依赖项来隔离错误消息。
Cannot derive uses clause from service loader invocation in: javax/ws/rs/client/FactoryFinder.find().
Cannot derive uses clause from service loader invocation in: javax/ws/rs/ext/FactoryFinder.find().
Cannot derive uses clause from service loader invocation in: javax/ws/rs/sse/FactoryFinder.find().
Cannot derive uses clause from service loader invocation in: javax/xml/bind/ServiceLoaderUtil.firstByServiceLoader().
ApplicationTest\build\jlinkbase\tmpjars\de.test.merged.module\module-info.java:154: error: the service implementation type must be a subtype of the service interface type, or have a public static no-args method named "provider" returning the service implementation
provides javax.ws.rs.ext.Providers with org.jboss.resteasy.plugins.interceptors.CacheControlFeature,
^
ApplicationTest\build\jlinkbase\tmpjars\de.test.merged.module\module-info.java:155: error: the service implementation type must be a subtype of the service interface type, or have a public static no-args method named "provider" returning the service implementation
org.jboss.resteasy.plugins.interceptors.encoding.ClientContentEncodingAnnotationFeature,
^
ApplicationTest\build\jlinkbase\tmpjars\de.test.merged.module\module-info.java:156: error: the service implementation type must be a subtype of the service interface type, or have a public static no-args method named "provider" returning the service implementation
org.jboss.resteasy.plugins.interceptors.encoding.MessageSanitizerContainerResponseFilter,
^
...
^
25 errors
package org.apache.logging.log4j.spi is not visible
(package org.apache.logging.log4j.spi is declared in module org.apache.logging.log4j, but module de.test.merged.module does not read it)
package org.apache.logging.log4j.message is not visible
(package org.apache.logging.log4j.message is declared in module org.apache.logging.log4j, but module de.test.merged.module does not read it)
module not found: java.activation
package javax.ws.rs.ext does not exist
package javax.ws.rs.ext does not exist
package javax.ws.rs.ext does not exist
我们现在一事无成。它很可能与modules-info.java有关,但是关于这个主题的说明和文档相当复杂,而且往往非常详细。我们只是想要一个可以在Intellij之外启动的应用程序。
我们对所有解决方案都持开放态度,只要它们奏效。我们不需要一个最先进的解决方案,但我们可以从某种方式获得一个EXE最终(也有一个外部工具的帮助)。我们的应用程序不一定要模块化,但我们既不得到它,也不解决它。
package de.test;
public class Main {
public static void main(String[] args) {
MainFX.main(args);
}
}
package de.test;
import ...;
public class MainFX extends Application {
public static void main(String[] args) {
launch();
}
@Override
public void start(Stage primaryStage) throws Exception {
...
}
}
gradle文件如下所示:
plugins {
id 'java'
id 'application'
}
group 'de.test'
version '1.0.8'
sourceCompatibility = 11
mainClassName = 'de.test.MainFX'
jar {
manifest {
attributes 'Main-Class': mainClassName
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile "commons-io:commons-io:2.6"
compile "org.apache.logging.log4j:log4j-api:2.11.2"
compile "dom4j:dom4j:1.6.1"
compile "commons-lang:commons-lang:2.6"
compile "axis:axis:1.4"
compile "jaxen:jaxen:1.1.6"
compile "net.java.dev.jna:platform:3.5.2"
compile "org.apache.poi:poi:4.1.0"
compile "org.apache.poi:poi-scratchpad:4.1.0"
compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.4"
compile "org.jboss.resteasy:resteasy-multipart-provider:3.7.0.Final"
compile "org.jboss.resteasy:resteasy-jackson2-provider:3.7.0.Final"
compile "org.apache.logging.log4j:log4j-core:2.11.2"
compile "org.jboss.resteasy:resteasy-client:3.7.0.Final"
compile "org.openjfx:javafx-graphics:11.0.2:win"
compile "org.openjfx:javafx-base:11.0.2:win"
compile "org.openjfx:javafx-controls:11.0.2:win"
compile "org.openjfx:javafx-fxml:11.0.2:win"
compile "org.openjfx:javafx-graphics:11.0.2:win"
}
结果是非常奇怪的java-jar applicationtest.jar返回
错误:找不到或加载主类DE.Test.MainFx,原因是:java.lang.ClassNotFoundException:DE.Test.MainFx
...
mainClassName = 'de.test.MainFX'
javafx {
version = 11
modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.web']
}
jar {
manifest {
attributes 'Main-Class': 'de.test.MainLauncher'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
> Exception in thread "main" 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 de.test.MainLauncher.main(MainLauncher.java:7) 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)
> ... 10 more
因此,我们再次添加了javafx的依赖项,结果如下:
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:222)
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 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$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 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 "main" 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 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$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:834)
根据我到目前为止的(痛苦的)经验,让一个大型JavaFX11+项目运行的唯一方法是将所有内容保留在类路径上(也是JavaFX依赖项),并像上一个示例中所做的那样,为主类使用该包装器。(你当前的分级文件是错误的,请看我上面的评论。)试图摆弄模组系统只会让你一无所获,只会浪费你的时间。
我目前正在做以下操作来创建一个exe(或Mac上的应用程序)。
一旦你想出了你需要的所有选项,这种方法就像一种魅力。
使用jlink
构建自己的运行时很简单。
JAVA_HOME=<the java version you want to use>
$JAVA_HOME/bin/jlink --no-header-files --no-man-pages --compress=2 --strip-debug \
--add-modules <a list of the required or just all modules> \
--output java-runtime
我遵循了https://blog.jetbrains.com/idea/2013/03/packaging-javafx-2-applications-in-intellij-idea-121/中的步骤 但是当我尝试构建工件时,在最后一步中,我得到了这个错误 错误:Java FX Packager:无法生成工件-FX:Deploy在此JDK中不可用 这里有一个快速测试的hello world应用程
我们正在努力将我们的API从Java8升级到Java11。 然而,我们需要同时支持Java8和Java11,因为所有客户端还没有准备好Java11。 如果我们可以使用Java 8和Java 11创建maven build,而不需要复制我们的存储库,也不需要对pom进行任何更改,这是可能的吗。每次为Java 8和Java 11创建构建之前都使用xml?
操作系统:Linux Mint 18.3,Eclipse“2019-06”。使用Gradle 5.4的Gradle包装器。 昨天,我花了大约4个小时试图在Eclipse中组合一个项目,当使用Java11时,这个项目实际上会运行并显示一个JavaFX场景。由于这里的帮助,我最终还是做到了。 但这只是Eclipse中一个沼泽标准的“Java项目”。我实际上需要做的是开发一个Gradle项目,使用Gro
我试图在Windows上用IntelliJ IDEA Ultimate中的JavaFX运行Gradle项目。JavaFX是在我们最新的Git push中添加的,在它开始工作之前。 JDK 11.0.5(来自Oracle站点,不是openJDK),我使用的是Java11,都在IntelliJ中配置 JDK安装目录(特别是/bin目录)添加到我的路径 JDK安装目录中添加的java_home环境变量
问题内容: 我已使用内置的Gradle支持在IntelliJ(2019.2)中设置了OpenJDK 12项目。为了设计使用JavaFX 12的GUI,我已经阅读并阅读了多次安装指南,在IDE中运行程序没有问题,问题是当我尝试构建要运行的发行版的.jar文件时陷入问题。到目前为止,我还没有找到一个可行的解决方案,而我搜索了很多QUITE,几乎为此扯掉了头发。当前,当我尝试使用java -jar“ j
我试着把我的主类移到一个不扩展Application的单独的类中,这就是导致上述错误的原因。如果不移动我的主类,我会得到一个不同的错误。 My Build.Gradle当前看起来如下所示: 如果我让我的main方法扩展应用程序,那么我会得到一个错误,说明找不到我的main类,尽管我可以看到它存在于生成的.jar文件中。 编辑 我试过指南的模块化部分。这样做,我有超过100个错误时,试图建立。它们都