使用 gradle 和 intellij 为 JavaFX 构建 FatJar,出现 NoClassDefFOundError

问题描述 投票:0回答:2

我已使用内置 Gradle 支持在 IntelliJ (2019.2) 中设置了 OpenJDK 12 项目。为了设计 GUI,我使用 JavaFX 12。我已经遵循并阅读了 setup 指南多次,在 IDE 中运行该程序没有任何问题,问题是当我尝试构建一个用于分发的 .jar 文件时我遇到了问题。到目前为止,我还没有找到有效的解决方案,而且我已经搜索了很多,几乎为此抓狂。目前,当我尝试使用 java -jar "jarName".jar 运行我的 jar 文件时,出现以下错误:

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:151)
        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 com.CAM.Starter.main(Starter.java:6)
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

我尝试将我的主类移动到一个不扩展应用程序的单独的类,这就是导致上述错误的原因。如果不移动我的主类,我会得到一个不同的错误。

我的 build.gradle 目前看起来像这样:

plugins {
    id 'java'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'
}

group 'ClassicAddonManager'
version '0.2'
sourceCompatibility = 11

repositories {
    mavenCentral()
}

javafx {
    version = "12.0.2"
    modules = [ 'javafx.controls', 'javafx.fxml' ]
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile 'net.sourceforge.htmlunit:htmlunit:2.13'
    compile group: 'com.google.code.gson', name: 'gson', version: '2.7'
    compile group: 'net.lingala.zip4j', name: 'zip4j', version: '1.2.4'
}

jar {
    manifest {
        attributes 'Main-Class': 'com.CAM.Starter'
    }
    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

如果我有扩展应用程序的主要方法,那么我会收到一条错误,指出无法找到我的主类,即使我可以看到它存在于生成的 .jar 文件中。

我想做的就是生成一个没有编程知识的朋友可以运行的文件。理想情况下,他们可以运行一个文件,而无需先安装 Java。我知道应该可以做到这一点,但 Gradle 对我来说是新的,所以我不确定这是否是导致所有这些头痛的原因。是否有更简单的部署方法?特别是考虑到这是一个个人项目?

编辑

我已经尝试过指南的模块化部分。尝试构建时,我遇到了 100 多个错误。它们都具有以下特点:

javafx.graphicsEmpty reads package org.xml.sax from both xml.apis and java.xml
java gradle intellij-idea javafx executable-jar
2个回答
15
投票

如果你想使用 Gradle 做一个 fat jar,而不是使用 Shadow 插件,通常你会这样做:

jar {
    manifest {
        attributes 'Main-Class': 'com.CAM.Starter'
    }
    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

但是,有一个重要事实:

compile
已弃用,JavaFX 插件默认使用
implementation
因此,

configuration.compile

可能为空,或者至少,它不会包含 JavaFX 类。

解决方案是检查

runtimeClasspath

配置,因为我们将在那里拥有所有类,并且我们可以制作胖罐子:

jar {
    manifest {
        attributes 'Main-Class': 'com.CAM.Starter'
    }
    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

这在 OpenJFX 文档中进行了解释,
https://openjfx.io/openjfx-docs/#modular

,非模块化项目部分,gradle 小节。 一旦你有了你的 fat jar,你就可以运行它:

java -jar yourFatJar.jar

请注意,双击它不起作用,详细解释见
这里

,因此可以方便地创建小批量。 更好的解决方案是做一个模块化项目并使用

jlink

创建运行时映像(它还包括启动器脚本)。您可以将此映像分发给其他甚至没有安装 JDK 的用户。使用 gradle,您只需包含

'org.beryx.jlink'
插件,就像在这个
sample
中一样。 您还可以使用

jpackage

早期版本来创建和分发安装程序。

    


0
投票
build.gradle

plugins {
    id 'org.beryx.jlink' version '2.25.0'
}

application {
    mainModule = 'com.example'
    mainClass = 'com.example.main'
}


jlink {
    imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip")
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
        name = 'YourAppName'
    }
}

然后您可以使用 Gradle 进行构建:

导航至

View

>

Tool Windows
>
Gradle
。在打开的窗口中,打开
Tasks/build
目录。双击
jlink
构建您的项目。输出的文件可以在
build/image/bin
找到,其中包含适用于 Unix 和 Windows 的可执行文件。
build
└── image
    └── bin
        ├── App
        └── App.bat

© www.soinside.com 2019 - 2024. All rights reserved.