2

我正在使用 JavaFX 11 (OpenFX) 运行一些应用程序。该应用程序是用 IntellijIdea 编写的,并使用 gradle 构建。在 IDE 中运行时一切正常。构建 jar 时它会成功构建,但是当我尝试执行它时出现错误:

Exception in thread "main" java.lang.NoClassDefFoundError: io/reactivex/subjects/Subject

要构建一个 jar,我使用 onslip.gradle-one-jar 插件。我的毕业典礼如下:

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 任务。

4

1 回答 1

2

您在构建中遇到的主要问题与您如何定义依赖关系implementationcompile不再)有关,而另一方面,您基于configurations.compile.

因为implementationcompile不一样,configurations.compile只包含你项目的类,不包含第三方依赖(包括JavaFX)。

运行构建任务将生成一个 3 KB 的非常小的 fat jar。显然,这个 jar 缺少依赖项中的所有类。

解决方案

在您的 jar 任务中替换configurations.compileconfigurations.compileClasspath

jar {
    from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
    manifest {
        attributes 'Main-Class': 'jetliner.Main'
    }
}

运行./gradlew build以生成一个胖 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 样本相比,加载它的时间太长了普通的脂肪罐。

如果你使用它是因为胖罐子没有运行,也许你需要一个Launcher,如下所述:

public class Launcher {
    public static void main(String[] args) {
        Main.main(args);
    }
}

然后将 mainClass 替换为jetliner.Launcher.

注意 2:JavaFX 插件(最新版本 0.0.7)使用implementation,它负责添加 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'
}
于 2019-01-22T18:50:14.430 回答