java.lang.NoClassDefFoundError : io/reactivex/subjects/Subject when building jar in Intellij Idea (gradle + JavaFX 11)

标签 java gradle rx-java2 javafx-11 openfx

我正在使用 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。

由于implementationcompile不同,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/

相关文章:

java - 我可以获取从 Swing 到资源管理器的文件路径吗

java - Play 2.0.4 更新使用 @EmbeddedId 的类时出现问题

gradle - 使用 gradle 0.8 复制文件树时如何强制包含空目录?

scala - 使用 Gradle 从单个源项目编译多个 jar

c - JNI 与 gradle

android - 链接多个用例

java - Android RxJava - GroupBy 和合并回来?

java - 如何在rxjava中添加公共(public)观察者

java - 来自一个 InputStream 的 2 个 BufferedReader

java - 在 Spring Boot 中存储 MongoDB 用户的可配置加密密码