使用gradle和intellij为JavaFX构建FatJar,获取NoClassDefFOundError [英] Building FatJar for JavaFX with gradle and intellij, getting NoClassDefFOundError

查看:117
本文介绍了使用gradle和intellij为JavaFX构建FatJar,获取NoClassDefFOundError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have set up an OpenJDK 12 project in IntelliJ (2019.2) using the built-in Gradle support. To design the GUI I'm using JavaFX 12. I have followed and read the setup guide several times, I have no issues running the program in my IDE, the issue is when I try to build a .jar file for distribution that I run into problems. I have not been able to find a solution that works so far and I've searched QUITE a lot, nearly tearing my hair out over this. Currently when i try to run my jar file with java -jar "jarName".jar I get the following error:

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

我尝试将主类移至一个不会扩展Application的单独类,这就是导致上述错误的原因.如果不移动我的主班,我会得到一个不同的错误.

I have tried moving my main class to a separate one that doesn't extend Application, which is what gives the above error. Without moving my Main class I get a different error.

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

My build.gradle looks like this currently:

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) }
    }
}

如果我有我的主要方法扩展Application,那么我会收到一条错误消息,指出即使我看到生成的.jar文件中也存在我的主类.

If I have my main method extending Application then I get an error stating that my main class could not be found even though I can see it is present in the generated .jar file.

我要做的就是生成一个文件,没有编程知识的朋友可以运行该文件.理想情况下,无需先安装Java就可以运行的文件.我知道应该可以这样做,但是Gradle对我来说是新手,所以我不确定这是否是造成所有头痛的原因.有潜在的更简单的部署方法吗?特别是考虑到这是一个单独的项目?

All I'm trying to do, is to generate a file that a friend with no knowledge of programming could run. Ideally, a file that they could run without having to install Java first. I know it should be possible to do this, but Gradle is new to me so I'm not sure if that is what is causing all this headache. Is there potentially an easier way to deploy? Especially given that this is a solo-project?

编辑

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

I have tried the modular part of the guide. Doing that I have over 100 error when attempting to build. They are all something in the vein of:

javafx.graphicsEmpty reads package org.xml.sax from both xml.apis and java.xml

推荐答案

如果您想使用Gradle而不是影子插件来制作胖子,通常您会这样做:

If you want to do a fat jar using Gradle but not a shadow plugin, usually you will do:

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

但是,有一个重要的事实:不推荐使用compile,而JavaFX插件通过

However, there is an important fact: compile is deprecated, and the JavaFX plugin uses implementation by default.

结果,configuration.compile可能为空,或者至少不包含JavaFX类.

As a consequence, configuration.compile might be empty, or at least, it won't contain the JavaFX classes.

解决方案是检查runtimeClasspath配置,因为这里将包含所有类,我们可以制作胖子罐:

The solution is to check the runtimeClasspath configuration, as we will have all the classes there, and we can make the fat jar:

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

OpenJFX文档 https://openjfx.io/openjfx-docs/#中对此进行了解释模块化,非模块化项目,gradle子项.

This is explained in the OpenJFX docs, https://openjfx.io/openjfx-docs/#modular, section non-modular projects, subsection gradle.

一旦有了胖子罐,您可以使用以下命令运行它:

Once you have your fat jar, you can run it with:

java -jar yourFatJar.jar

请注意,双击该按钮将无效,如详细说明

Note that double-clicking on it won't work, as explained in detail here, so it can be convenient to create a small batch instead.

一个更好的解决方案是执行一个模块化项目,并使用jlink创建一个运行时映像(它还包括一个启动程序脚本).您可以将该映像分发给甚至没有安装JDK的其他用户.使用gradle,您可以仅包含'org.beryx.jlink'插件,例如在样本.

A better solution is to do a modular project and use jlink to create a runtime image (it also includes a launcher script). You can distribute this image to other users that don't have even JDK installed. With gradle, you can just include the 'org.beryx.jlink' plugin, like in this sample.

您还可以使用jpackage早期版本来创建分发安装程序.

And you can also use the early version of jpackage to create an distribute an installer.

这篇关于使用gradle和intellij为JavaFX构建FatJar,获取NoClassDefFOundError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆