【问题标题】:java.lang.NoClassDefFoundError: io/reactivex/subjects/Subject when building jar in Intellij Idea (gradle + JavaFX 11)java.lang.NoClassDefFoundError: io/reactivex/subjects/Subject 在 Intellij Idea 中构建 jar (gradle + JavaFX 11)
【发布时间】:2019-06-15 21:38:33
【问题描述】:

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

【问题讨论】:

  • 你如何尝试启动它?
  • 我运行 awesomeFunJar 任务,它从 com.github.onslip.gradle-one-jar 插件执行构建功能
  • 可以构建,但是当你说“当我尝试执行它时”?
  • 在 IDE finder 中,右键单击构建的 jar 文件,然后选择运行。
  • 有些奇怪,因为您的 gradle 文件定义了mainClassName = 'jetliner.Main',但运行操作似乎愿意启动io/reactivex/subjects/Subject 之一,也许您的启动器配置有问题?

标签: java gradle rx-java2 javafx-11 openfx


【解决方案1】:

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

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

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

解决方案

configurations.compileClasspath替换你的jar任务configurations.compile

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与普通的脂肪罐相比,加载样本的时间真的太长了。

如果你因为胖 jar 不运行而使用它,也许你需要一个 Launcher 类,正如 here 解释的那样:

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

然后用jetliner.Launcher替换mainClass。

注意 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'
}

【讨论】:

  • 非常感谢!使用您在注释 2 中提供的 gradle,我已经成功构建并执行了 jar。唯一的小注意是mainClassName = 'jetliner.Launcher'需要保留,否则应用将无法运行./gradlew run
  • 是的,对,我错过了粘贴它,对不起。我会更新答案。
猜你喜欢
  • 2020-10-18
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
  • 2016-09-03
  • 1970-01-01
  • 2021-08-15
  • 2019-03-05
相关资源
最近更新 更多