Java 11、JavaFX、Gradle、Eclipse,令人讨厌的失败消息

Posted

技术标签:

【中文标题】Java 11、JavaFX、Gradle、Eclipse,令人讨厌的失败消息【英文标题】:Java 11, JavaFX, Gradle, Eclipse, nasty failure message 【发布时间】:2020-01-27 05:44:21 【问题描述】:

操作系统:Linux Mint 18.3,Eclipse“2019-06”。使用 Gradle 5.4 的 Gradle 包装器。

昨天我花了大约 4 个小时尝试在 Eclipse 中组合一个项目,该项目将在使用 Java 11 时实际运行并显示 JavaFX 场景。在here 的帮助下,我最终管理了它。

但这只是 Eclipse 中的一个沼泽标准“Java 项目”。我真正需要做的是开发一个 Gradle 项目,使用 Groovy 作为主要语言。

再次,我从同一位男士 José Pereda 那里找到了this answer。这可以通过下面的测试完成 Gradle“构建”。但是,当我使用 Gradle“应用程序”插件的任务“运行”时,我收到一条令人讨厌的消息:“错误:JavaFX 运行时组件丢失,并且需要运行此应用程序”。无论我是从 Eclipse 内部还是从终端运行,我都会得到这个。

这是我的 build.gradle:

plugins 
     id 'java-library'
     id 'groovy'
     id 'eclipse'
     id 'application'
     id 'java'

mainClassName = 'core.App'
group 'Project'
version '1.0'
sourceCompatibility = 1.11
repositories 
     mavenCentral()

def currentOS = org.gradle.internal.os.OperatingSystem.current()
def platform
if (currentOS.isWindows()) 
     platform = 'win'
 else if (currentOS.isLinux()) 
     platform = 'linux'
 else if (currentOS.isMacOsX()) 
     platform = 'mac'

dependencies 
     api 'org.apache.commons:commons-math3:3.6.1'
     implementation 'com.google.guava:guava:27.0.1-jre'
     testImplementation 'junit:junit:4.12'
     implementation 'org.codehaus.groovy:groovy-all:2.5.8'
     testImplementation 'org.spockframework:spock-core:1.2-groovy-2.5'
     // these seemed to do the trick for a simple "Java project"
     // ... but Gradle seems to want something else (?)
     implementation "org.openjfx:javafx-base:11:$platform"
     implementation "org.openjfx:javafx-graphics:11:$platform"
     implementation "org.openjfx:javafx-controls:11:$platform"
     implementation "org.openjfx:javafx-fxml:11:$platform"

这是我的应用程序代码:

import javafx.application.Application
import javafx.stage.Stage

class App extends Application 
    @Override
    public void start(Stage primaryStage) throws Exception 
        println "start...."
    

    public static void main(String[] args) 
        println "about to launch..."
        launch(args);
        println "...launched"
    

这是我的测试:

class FuncSpec extends Specification 
    def "JavaFX should run OK"()
        when:
        App app = new App()

        then:
        true
    

Gradle“运行”后终端中的完整输出如下:

mike@M17A ~/software projects/eclipse-workspace/GrVocabSearch2019-09 $  ./gradlew run

> Task :run FAILED
Error: JavaFX runtime components are missing, and are required to run this application

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':run'.
> Process 'command '/usr/lib/jvm/java-11-openjdk-amd64/bin/java'' finished with non-zero exit value 1

稍后

在我的 build.gradle 中按照 José Pereda 的指示进行操作。这就是我尝试执行“运行”任务的过程:

> Task :run FAILED
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/media/chris/W10%20D%20drive/apps/Chris.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.8/2f1e8ea55e625fe51e85ef35eb067f1d9c61772d/groovy-2.5.8.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Error: class jdk.internal.reflect.NativeMethodAccessorImpl is not a subclass of javafx.application.Application
        at javafx.graphics/javafx.application.Application.launch(Application.java:298)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
        at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1491)
        at org.codehaus.groovy.runtime.callsite.StaticMetaClassSite.callStatic(StaticMetaClassSite.java:62)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:55)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:196)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:208)
        at core.App.main(main.groovy:60)
        ... 11 more
Exception running application core.App

FAILURE: Build failed with an exception

注意

我相信这不是任何未提及 Gradle 的答案的重复。我已经在正常的 Java 运行中得到了这个。

【问题讨论】:

JavaFX 不再与 Java 11 捆绑在一起。您必须单独包含它。 Error: JavaFX runtime components are missing, and are required to run this application with JDK 11的可能重复 您缺少包含 VM 参数; JavaFX 模块应该转到--module-path,您应该将所需的模块包含在--add-modules 中。这可以添加到run 任务中,并且应该这样做。或者,您可以制作一个胖罐(就像您链接的第二个答案一样)。但是,您可以通过使用 JavaFX gradle 插件来简化所有这些操作,例如 here。我建议您也阅读入门指南guide。 【参考方案1】:

问题原因:

错误:JavaFX 运行时组件丢失,是运行此应用程序所必需的

已经回答了很多次(包括使用 Gradle),但是由于您仍然使用“旧”方法来包含 JavaFX 依赖项,而不是使用 JavaFX 插件,我将解释如何解决这个问题。

错误

如果您查看Eclipse 的 JavaFX 文档,IDE 部分(模块化或非模块化项目),对此问题有明确的解释:

或者,换句话说,JavaFX 依赖项是模块化的,必须添加到模块路径中。

第一个解决方案

如果您继续阅读,您会立即找到有关如何修复它的说明(前提是您没有使用构建工具):

但是,由于您使用的是 Gradle,因此必须调整解决方案以包含在您的构建文件中。

这是使用JavaFX插件之前完成的方式:

compileJava 
    doFirst 
        options.compilerArgs = [
                '--module-path', classpath.asPath,
                '--add-modules', 'javafx.controls,javafx.fxml'
        ]
    


run 
    doFirst 
        jvmArgs = [
                '--module-path', classpath.asPath,
                '--add-modules', 'javafx.controls,javafx.fxml'
        ]
    

现在你应该可以运行了:

./gradlew run

顺便说一句,在使用插件之前,您仍然可以看到 here 文档中提到的 HelloFX 示例的构建。

JavaFX 插件

Gradle 的 JavaFX plugin 正是为了处理构建文件中的所有“样板代码”而创建的。

如果您现在查看 Eclipse 文档、Gradle 部分(模块化或非模块化)或相同的更新 sample,您将看到构建文件已简化为:

plugins 
  id 'application'
  id 'org.openjfx.javafxplugin' version '0.0.8'


repositories 
    mavenCentral()


dependencies 


javafx 
    version = "13"
    modules = [ 'javafx.controls', 'javafx.fxml' ]


mainClassName = 'org.openjfx.MainApp'

在您的情况下,您只需将其适应您的构建文件,例如:

plugins 
    id 'java-library'
    id 'groovy'
    id 'eclipse'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'


mainClassName = 'core.App'
group 'Project'
version '1.0'
sourceCompatibility = 11

repositories 
    mavenCentral()


dependencies 
    api 'org.apache.commons:commons-math3:3.6.1'
    implementation 'com.google.guava:guava:27.0.1-jre'
    testImplementation 'junit:junit:4.12'
    implementation 'org.codehaus.groovy:groovy-all:2.5.8'
    testImplementation 'org.spockframework:spock-core:1.2-groovy-2.5'


javafx 
    version = "13"
    modules = [ "javafx.controls", "javafx.fxml" ]

然后运行:

./gradlew run

【讨论】:

非常感谢。我已经完全按照您对插件的说法更改了我的构建文件。我仍然遇到异常。请参阅问题更新。很自然,我现在(或明天)将看看这是否适用于 Java(没有 Groovy)。我也会尝试旧方法。 应用程序类必须是公开的。见this。 谢谢。我刚刚公开了。没有骰子,同样的例外。 再次感谢。不行:编译失败:“意外的令牌”。可能launch 方法现在只能接受 1 个参数。我必须检查来源。顺便问一下,JavaFX 版本是否必须与 Java 版本相同?你放了“13”,我试过“11”和“13”。明天再做一些实验。您的帮助非常宝贵,再次感谢。 有一个launch(class, args) method。您可以使用 JavaFX 11、12 或 13。

以上是关于Java 11、JavaFX、Gradle、Eclipse,令人讨厌的失败消息的主要内容,如果未能解决你的问题,请参考以下文章

Gradle OpenJFx11:错误 - 缺少 JavaFx 运行时组件

java javafx的gradle

IntelliJ + Gradle + JavaFX 构建,但未运行

使用 Gradle 构建 JavaFX 应用程序

使用 Gradle 在 Android 中构建 JavaFX 应用程序

使用 Gradle 在 IntelliJ 中运行 JavaFX 项目