我正在使用 JavaFX 11 (OpenFX) 运行一些应用程序。该应用程序是用 IntellijIdea 编写的,并使用 gradle 构建。在IDE中运行一切正常。构建 jar 时,它构建成功,但当我尝试执行它时,出现错误:
Exception in thread "main" java.lang.NoClassDefFoundError: io/reactivex/subjects/Subject
为了构建一个 jar,我使用onslip.gradle-one-jar 插件。我的 gradle 如下:
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.5'
id 'com.github.onslip.gradle-one-jar' version '1.0.5'
}
repositories {
mavenCentral()
}
dependencies {
implementation "org.openjfx:javafx-base:11:win"
implementation "org.openjfx:javafx-graphics:11:win"
implementation "org.openjfx:javafx-controls:11:win"
implementation "org.openjfx:javafx-fxml:11:win"
implementation 'com.jfoenix:jfoenix:9.0.8'
implementation group: 'commons-validator', name: 'commons-validator', version: '1.6'
implementation group: 'commons-io', name: 'commons-io', version: '2.6'
implementation group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.141.59'
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'
implementation group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2'
implementation group: 'io.reactivex.rxjava2', name: 'rxjava', version: '2.2.5'
testImplementation group: 'junit', name: 'junit', version: '4.12'
}
javafx {
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
mainClassName = 'jetliner.Main'
jar {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest {
attributes 'Main-Class': 'jetliner.Main'
}
}
task awesomeFunJar(type: OneJar) {
mainClass = 'jetliner.Main'
}
对于 jar 构建,我运行 AwesomeFunJar 任务。
最佳答案
构建中遇到的主要问题与如何使用实现
(不再是编译
)定义依赖关系有关,而另一方面,您构建自己的基于 configurations.compile
的 jar。
由于implementation
和compile
不同,configurations.compile
仅包含您项目的类,而不包含第三方依赖项(包括 JavaFX)。
运行构建任务将生成一个非常小的 3 KB 的 fat jar。显然这个 jar 缺少依赖项中的所有类。
解决方案
将 jar 任务中的 configurations.compile
替换为 configurations.compileClasspath
:
jar {
from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
manifest {
attributes 'Main-Class': 'jetliner.Main'
}
}
运行 ./gradlew build
以生成一个 fat jar(大约 23 MB,具有给定的依赖项),可以使用以下命令运行:
java -jar build/libs/myproject.jar
或者运行 ./gradlew AwesomeFunJar
来生成一个类似的 fat jar (21 MB),其运行方式为:
java -jar build/libs/myproject-standalone.jar
在这两种情况下,都包含 io.reactivex.rxjava2
依赖项。
注1:我之前没有使用过这个 gradle-one-jar 插件,而且我没有看到自定义加载程序有任何主要优势,我所看到的只是对于 helloFX与普通的脂肪 jar 相比,样本的加载时间确实太长了。
如果您因为 fat jar 无法运行而使用它,也许您需要一个 Launcher
类,如所述 here :
public class Launcher {
public static void main(String[] args) {
Main.main(args);
}
}
然后将 mainClass 替换为 jetliner.Launcher
。
注释2:JavaFX插件(最新版本0.0.7)使用实现
,它负责添加JavaFX依赖项,因此您可以简化构建文件:
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.7'
id 'com.github.onslip.gradle-one-jar' version '1.0.5'
}
repositories {
jcenter()
}
dependencies {
implementation 'com.jfoenix:jfoenix:9.0.8'
implementation group: 'commons-validator', name: 'commons-validator', version: '1.6'
implementation group: 'commons-io', name: 'commons-io', version: '2.6'
implementation group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.141.59'
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'
implementation group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2'
implementation group: 'io.reactivex.rxjava2', name: 'rxjava', version: '2.2.5'
testImplementation group: 'junit', name: 'junit', version: '4.12'
}
javafx {
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
mainClassName = 'jetliner.Launcher'
jar {
manifest {
attributes 'Main-Class': 'jetliner.Launcher'
}
from {
configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
task awesomeFunJar(type: OneJar) {
mainClass = 'jetliner.Main'
}
关于java.lang.NoClassDefFoundError : io/reactivex/subjects/Subject when building jar in Intellij Idea (gradle + JavaFX 11),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54307903/