3

I've been trying to download JavaFX for a project and my laptop is just not having it when I try to gradle run.

I can gradle build just fine but when I try gradle run I get this message:

> Configure project :
Project : => no module-info.java found

> Task :run FAILED
Loading library prism_es2 from resource failed: java.lang.UnsatisfiedLinkError: /Users/claretian/.openjfx/cache/20+19/aarch64/libprism_es2.dylib: dlopen(/Users/claretian/.openjfx/cache/20+19/aarch64/libprism_es2.dylib, 0x0001): tried: '/Users/claretian/.openjfx/cache/20+19/aarch64/libprism_es2.dylib' (mach-o file, but is an incompatible architecture (have (x86_64), need (arm64e)))
java.lang.UnsatisfiedLinkError: /Users/claretian/.openjfx/cache/20+19/aarch64/libprism_es2.dylib: dlopen(/Users/claretian/.openjfx/cache/20+19/aarch64/libprism_es2.dylib, 0x0001): tried: '/Users/claretian/.openjfx/cache/20+19/aarch64/libprism_es2.dylib' (mach-o file, but is an incompatible architecture (have (x86_64), need (arm64e)))
        at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
        at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:331)
        at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:197)
        at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:139)
        at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2404)
        at java.base/java.lang.Runtime.load0(Runtime.java:817)
        at java.base/java.lang.System.load(System.java:2015)
        at javafx.graphics@20/com.sun.glass.utils.NativeLibLoader.installLibraryFromResource(NativeLibLoader.java:217)
        at javafx.graphics@20/com.sun.glass.utils.NativeLibLoader.loadLibraryFromResource(NativeLibLoader.java:197)
        at javafx.graphics@20/com.sun.glass.utils.NativeLibLoader.loadLibraryInternal(NativeLibLoader.java:138)
        at javafx.graphics@20/com.sun.glass.utils.NativeLibLoader.loadLibrary(NativeLibLoader.java:54)
        at javafx.graphics@20/com.sun.prism.es2.ES2Pipeline.lambda$static$0(ES2Pipeline.java:63)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:319)
        at javafx.graphics@20/com.sun.prism.es2.ES2Pipeline.<clinit>(ES2Pipeline.java:52)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:391)
        at java.base/java.lang.Class.forName(Class.java:382)
        at javafx.graphics@20/com.sun.prism.GraphicsPipeline.createPipeline(GraphicsPipeline.java:218)
        at javafx.graphics@20/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:92)
        at javafx.graphics@20/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
        at java.base/java.lang.Thread.run(Thread.java:1623)
Loading library prism_sw from resource failed: java.lang.UnsatisfiedLinkError: /Users/claretian/.openjfx/cache/20+19/aarch64/libprism_sw.dylib: dlopen(/Users/claretian/.openjfx/cache/20+19/aarch64/libprism_sw.dylib, 0x0001): tried: '/Users/claretian/.openjfx/cache/20+19/aarch64/libprism_sw.dylib' (mach-o file, but is an incompatible architecture (have (x86_64), need (arm64e)))
java.lang.UnsatisfiedLinkError: /Users/claretian/.openjfx/cache/20+19/aarch64/libprism_sw.dylib: dlopen(/Users/claretian/.openjfx/cache/20+19/aarch64/libprism_sw.dylib, 0x0001): tried: '/Users/claretian/.openjfx/cache/20+19/aarch64/libprism_sw.dylib' (mach-o file, but is an incompatible architecture (have (x86_64), need (arm64e)))
        at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
        at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:331)
        at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:197)
        at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:139)
        at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2404)
        at java.base/java.lang.Runtime.load0(Runtime.java:817)
        at java.base/java.lang.System.load(System.java:2015)
        at javafx.graphics@20/com.sun.glass.utils.NativeLibLoader.installLibraryFromResource(NativeLibLoader.java:217)
        at javafx.graphics@20/com.sun.glass.utils.NativeLibLoader.loadLibraryFromResource(NativeLibLoader.java:197)
        at javafx.graphics@20/com.sun.glass.utils.NativeLibLoader.loadLibraryInternal(NativeLibLoader.java:138)
        at javafx.graphics@20/com.sun.glass.utils.NativeLibLoader.loadLibrary(NativeLibLoader.java:54)
        at javafx.graphics@20/com.sun.prism.sw.SWPipeline.lambda$static$0(SWPipeline.java:43)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:319)
        at javafx.graphics@20/com.sun.prism.sw.SWPipeline.<clinit>(SWPipeline.java:42)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:391)
        at java.base/java.lang.Class.forName(Class.java:382)
        at javafx.graphics@20/com.sun.prism.GraphicsPipeline.createPipeline(GraphicsPipeline.java:218)
        at javafx.graphics@20/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:92)
        at javafx.graphics@20/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
        at java.base/java.lang.Thread.run(Thread.java:1623)
Graphics Device initialization failed for :  es2, sw
Error initializing QuantumRenderer: no suitable pipeline found
java.lang.RuntimeException: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found
        at javafx.graphics@20/com.sun.javafx.tk.quantum.QuantumRenderer.getInstance(QuantumRenderer.java:283)
        at javafx.graphics@20/com.sun.javafx.tk.quantum.QuantumToolkit.init(QuantumToolkit.java:253)
        at javafx.graphics@20/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:263)
        at javafx.graphics@20/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:290)
        at javafx.graphics@20/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:162)
        at javafx.graphics@20/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:651)
        at javafx.graphics@20/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:409)
        at javafx.graphics@20/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
        at java.base/java.lang.reflect.Method.invoke(Method.java:578)
        at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1081)
Caused by: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found
        at javafx.graphics@20/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:95)
        at javafx.graphics@20/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
        at java.base/java.lang.Thread.run(Thread.java:1623)
Exception in thread "main" java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:119)
        at java.base/java.lang.reflect.Method.invoke(Method.java:578)
        at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1081)
Caused by: java.lang.RuntimeException: No toolkit found
        at javafx.graphics@20/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:275)
        at javafx.graphics@20/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:290)
        at javafx.graphics@20/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:162)
        at javafx.graphics@20/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:651)
        at javafx.graphics@20/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:409)
        at javafx.graphics@20/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
        ... 2 more

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':run'.
> Process 'command '/Users/claretian/.sdkman/candidates/java/20.0.2-amzn/bin/java'' finished with non-zero exit value 1

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 2s
3 actionable tasks: 2 executed, 1 up-to-date

I'm pretty sure it's to do with the architecture being incompatible but I've tried to download every version of JavaFX I could find.

Clare Tian
  • 31
  • 1

1 Answers1

4

tl;dr

You seem to have two problems:

  • Missing module-java.java file necessary for a modularized app
  • Wrong installation of JavaFX, for Intel chips rather than Apple Silicon chips like the M1.

Modularize

Apparently some part of your configuration, or some library, expects your project to be modularized per Java Platform Module System (JPMS). I say this because of your error:

Project : => no module-info.java found

The module-java.java file is where you specify your module configuration. Apparently you do not have one.

Obtaining JavaFX technology

Three routes to accessing JavaFX:

  • Manually download JavaFX implementation. See the Gluon downloads page.
  • Have Gradle download libraries, to be a part of your development project
  • Develop and deploy using a JDK that comes bundled with the JavaFX/OpenJFX libraries

For someone starting out dabbling with JavaFX, I suggest the bundled-with-JDK option.

Download libraries

You can tell Gradle to download the necessary OpenJFX libraries that implement JavaFX.

One easy way to do that is to use the JavaFX new-project template bundled with IntelliJ IDE.

screenshot of IntelliJ new-project template dialog for JavaFX

After updating the version numbers to the latest, your build.gradle file might look like the following.

plugins {
    id 'java'
    id 'application'
    id 'org.javamodularity.moduleplugin' version '1.8.12'
    id 'org.openjfx.javafxplugin' version '0.0.13'
    id 'org.beryx.jlink' version '2.26.0'
}

group 'work.basil.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

ext {
    junitVersion = '5.10.0'
}

sourceCompatibility = '20'
targetCompatibility = '20'

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

application {
    mainModule = 'work.basil.example.exfx'
    mainClass = 'work.basil.example.exfx.HelloApplication'
}

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

dependencies {

    testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
}

test {
    useJUnitPlatform()
}

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

jlinkZip {
    group = 'distribution'
}

CAUTION… One major problem with the Gradle version of IntelliJ’s new-project template for JavaFX: The project is not modularized for Java Platform Module System (JPMS). This may be okay for dabbling with JavaFX. But for professional development, you will likely want your project to be modularized so you can use jlink to bundle a slimmed-down JVM as part of your final app artifact. This lack of modularization surprised me as the Maven edition of their new-project template does indeed produce a project already configured to be modularized.

JDK bundled with JavaFX

At least two of the several JDK vendors provide an edition of the JDK products that include the necessary OpenJFX libraries that implement JavaFX.

Those companies may also sell support for JavaFX, as might the co-leaders of JavaFX, Gluon and Oracle.

To most easily download and install these JDKs, I suggest installing SDKMAN! on your Mac. That handy bundle of shell scripts makes the download/install/uninstall chore quite simple and convenient. Just run this:

% sdk install java 17.0.8.fx-zulu  

… to get this:

Downloading: java 17.0.8.fx-zulu

In progress...

########################################################################################################################### 100.0%

Repackaging Java 17.0.8.fx-zulu...

Done repackaging...

Installing: java 17.0.8.fx-zulu
Done installing!

Do you want java 17.0.8.fx-zulu to be set as default? (Y/n): Y

To see a list of all JDK products available via SDKMAN!, run this:

sdk list java

Native code

Be aware that JavaFX is not pure Java. The needed libraries contain some native code specific to the particular host OS, and specific to the particular host machine’s chip (instruction set architecture).

For your M1 Mac, you need an edition of JavaFX for macOS running on Macs with Apple Silicon. You may see options for aarch64 or ARM, which are compatible with Apple Silicon.

  • I am guessing Gradle must automatically detect your host environment and download the appropriate version.
  • If using the bundled-with-JDK route, for your particular Mac, be sure to obtain an edition for macOS on Apple Silicon/aarch65/ARM rather than for Intel/x64/x86-64 in older Macs.

Your error message suggests that you have indeed installed for the wrong chip architecture:

mach-o file, but is an incompatible architecture (have (x86_64), need (arm64e)

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • "_Project : => no module-info.java found_" – That comes from the `org.javamodularity.moduleplugin` plugin, which is implicitly applied by the `org.openjfx.javafxplugin` plugin, by the way. And it's actually the latter plugin that handles downloading the correct JavaFX artifact for the current platform (detected via [osdetector-gradle-plugin](https://github.com/google/osdetector-gradle-plugin)). Note this implemented using classifiers and works better in Maven, as transitive dependency resolution appears to break in Gradle when using classifiers. – Slaw Aug 28 '23 at 14:49
  • That's why I consider the Gradle JavaFX plugin _required_ when developing a JavaFX application with Gradle (unless you're using a JDK that includes JavaFX). Though I've always wondered if Gradle's so-called "variants" would make it easier to work with JavaFX in Gradle. Not very familiar with that feature, however, and it would require changes to the OpenJFX build file(s), if I understand correctly. – Slaw Aug 28 '23 at 14:52
  • "_For someone starting out dabbling with JavaFX, I suggest the bundled-with-JDK option_" – If viable, I would suggest using the bundled-with-JDK option always, as then `jlink` / `jpackage` will implicitly use the JMOD files of the JavaFX modules. Otherwise, you have to download them from Gluon and point to them manually. [Using the JMOD files is "cleaner" than the native-code-embedded-in-JARs Maven artifacts](https://stackoverflow.com/a/61294909/6395627). The embedded approach requires extracting the native code (done automatically) before it can be used. – Slaw Aug 28 '23 at 14:59
  • 1
    "_But for professional development, you will likely want your project to be modularized so you can use jlink to bundle_" – Not always practical, as many libraries have yet to go modular, if they ever will. There are tools that attempt to make non-modular deps into modular deps while packaging an application, but I don't know how well that works. Though I want to point out this is only a problem when _only_ using `jlink`. The `jpackage` tool can work with non-modular applications (meaning you can have some deps, e.g., JavaFX, in the run-time image, and put everything else on the class-path). – Slaw Aug 28 '23 at 15:08
  • 1
    @Slaw May I suggest you create a Question and Answer to explain your points raised here? Building a JavaFX app for deployment is a complex and confusing process that desperately needs better documentation. – Basil Bourque Aug 28 '23 at 17:49
  • For reference, [`https://jdk.java.net`](https://jdk.java.net) hosts recent OpenJDK builds for both x86 and AArch64. – trashgod Aug 28 '23 at 17:54