How to open JavaFX .jar file with JDK 11?

24,047

Solution 1

Providing you have a simple (non-modular) JavaFX 11 project (without Maven/Gradle build tools), and you are using IntelliJ, like the HelloFX sample from here, this is how you can create a jar from IntelliJ that can be run from the console

A full tutorial on how to run the project can be found here, and instructions on how to create a jar are here (see section Non-modular project), but these doesn't cover Artifacts from IntelliJ.

Check that the HelloFX project runs from IntelliJ with these VM options:

--module-path ${PATH_TO_FX} --add-modules javafx.controls,javafx.fxml

where PATH_TO_FX has been set in File -> Settings -> Appearance & Behavior -> Path Variables, pointing to the JavaFX SDK lib.

Semi fat Jar

We can create a Jar that only contains the classes from the project, and third party dependencies, but not JavaFX ones.

Go to File -> Project Structure -> Artifacts -> Add -> JAR -> From modules with dependencies, add your main class, accept.

Then remove the JavaFX jars from the list, and accept.

SemiJar

Build the project, it will create a quite small jar (3 KB in this case).

Now you should be able to run it like:

java --module-path %PATH_TO_FX% --add-modules javafx.controls,javafx.fxml -jar out\artifacts\HelloFX_jar\HelloFX.jar

(make sure that %PATH_TO_FX% points to a valid folder and use quotes if it contains spaces.

You can distribute this jar, and run it in other platforms, providing those also have the JavaFX SDK.

Fat Jar

If you want a full fat jar that includes JavaFX dependencies, you can still use Artifacts.

Go to File -> Project Structure -> Artifacts -> Add -> JAR -> From modules with dependencies, add your main class, accept.

Then keep the JavaFX jars from the list, and accept. Build the project.

In theory, you should be able to run it like:

java -jar out\artifacts\HelloFX_jar\HelloFX.jar

But this won't work.

Reason 1: You need a launcher class, as explained here.

So create a launcher class:

public class Launcher {

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

Reason 2: If you only add your SDK jars to the fat jar, you will be missing the native libraries, as explained here.

So edit the artifact, select the Launcher class as main class, and add the native libraries (Directory Content -> path-to/JavaFX SDK/bin on Windows):

Fat Jar

Now build the project (now the jar is about 33 MB, and contains unnecessary native libraries) and run:

java -jar out\artifacts\HelloFX_jar\HelloFX.jar

You can distribute this jar, but only to Windows platforms.

You can create similar jars for other platforms, if you download their JavaFX SDKs, and you can also build cross-platform jars if you add them all together, as explained in the linked answers above.

Anyway, you should consider using jlink instead.

Note

About this error:

Caused by: java.lang.ClassNotFoundException: Files\Java\javafx-sdk-11.0.1\lib

it looks like the library path was set without quotes and it is missing the first part of the path C:\Program Files\.... Just make sure you use quotes:

set PATH_TO_FX="C:\Program Files\Java\javafx-sdk-11.0.1\lib"

Solution 2

I had the similar issue exporting/generating an Jar using JavaFX and IntelliJ Non-modular with Gradle (https://openjfx.io/openjfx-docs/)

The jar I was generating using Gradle jar command does not run and throws error saying it can not find my Main Class. When I opened my jar I was able to locate my main class. So I realized the error has to do with Jar Packaging.

enter image description here

I fixed the problem by adding JavaFX SDK to my Java SDk in IntelliJ as shown below.

enter image description here

After this I use the regular Gradle build Jar command to generate my Jar file (as shown below) and it runs Normally.

enter image description here

Solution 3

The easiest way to do this is to use an OpenJDK build that include JavaFX. Both Bellsoft and Azul produce such builds.

For Azul's Zulu builds of OpenJDK: https://www.azul.com/downloads/zulu-community/?version=java-11-lts&package=jdk-fx

For Bellsoft Liberica JDK: https://bell-sw.com/pages/downloads/#/java-11-lts and choose "Full JDK"

These builds are basically OpenJDK with the OpenJFX JavaFX modules added. Though be careful as some aspects of JavaFX may not be supported on LibericaFX. See https://bell-sw.com/pages/liberica-release-notes-11.0.9.1/

Solution 4

The above answers apply to non-modular JavaFX projects. To get a modular JavaFX project (with modular dependencies) running I used jlink.

Take the JavaFX SDK from https://gluonhq.com/products/javafx/; unzip the files to a directory, and point a shell variable JFX_LIB to the unzipped lib/ directory.

Take the JavaFX jmods (not SDK) file from https://gluonhq.com/products/javafx/; unzip the jmods, they are in a folder similar to javafx-jmods-11.0.2/. Point a shell variable JMOD_PATH to the unzipped directory javafx-jmods-11.0.2/.

Compile, sending your compiled classes to the directory mods/:

javac -d mods  --module-source-path src --module-path $JFX_LIB/javafx.graphics.jar:$JFX_LIB/javafx.base.jar:$JFX_LIB/javafx.controls.jar --module com.mymodule

Create a custom JRE with jlink, referring to the module path containing the JavaFX mods and your own compiled mod:

jlink --module-path $JMOD_PATH:mods --add-modules com.mymodule --output customjre

Run:

customjre/bin/java --module com.mymodule/com.mymodule.Main

(I tried for a LONG TIME to get a java -jar running with --module-path and --add-modules. I always got the following error:)

Error: Could not find or load main class com.mymodule.Main
Caused by: java.lang.NoClassDefFoundError: javafx/application/Application
Share:
24,047

Related videos on Youtube

DrMorteza
Author by

DrMorteza

I love it.

Updated on July 09, 2022

Comments

  • DrMorteza
    DrMorteza almost 2 years

    I created a JavaFX project in IntelliJ. I can run project in IntelliJ. I added below code in Configurations):

    --module-path ${PATH_TO_FX} --add-modules=javafx.controls,javafx.fxml
    

    But the output .jar file of project (made with Artifects) doesn't run. I tested these commands, but didn't get any chance:

    java  --module-path %PATH_TO_FX% --add-modules javafx.controls,javafx.fxml -jar Timer.jar
    java  --module-path %PATH_TO_FX% --add-modules javafx.controls  Timer.jar
    

    Last error log of command line:

    Error: Could not find or load main class Files\Java\javafx-sdk-11.0.1\lib
    Caused by: java.lang.ClassNotFoundException: Files\Java\javafx-sdk-11.0.1\lib
    

    p.s: I could run .jar file of this project when build on JDK-10

    EDIT:

    I downloaded JavaFX and added it's lib folder to System Environments. for adding JavaFX to project I did this process: Project Structure > Libraries > add > Java > JavaFxPath/lib

    Then I created Artifect for output jar file in this process: Project Structure > Artifects > Add > JAR > From Modules with dependencies > main Class : main.Main.

    • DrMorteza
      DrMorteza over 5 years
      Yes. I have main-class in that. With Build Artifects in IntelliJ options
    • Naman
      Naman over 5 years
      What is the output if you run java -jar Timer.jar --module-path %PATH_TO_FX% --add-modules javafx.controls ? and when you run java --module-path .../javafx-sdk-11/lib --add-modules=javafx.controls,javafx.fxml -classpath "<path to Timer.jar>" sample.Main ?
    • DrMorteza
      DrMorteza over 5 years
      This error given: Error: Could not find or load main class Files\Java\javafx-sdk-11.0.1\lib Caused by: java.lang.ClassNotFoundException: Files\Java\javafx-sdk-11.0.1\lib
    • DrMorteza
      DrMorteza over 5 years
      Error for your second approach: Error occurred during initialization of boot layer java.lang.module.FindException: Module javafx.controls not found
    • Naman
      Naman over 5 years
      Since the same module has been explicitly specified in the modulepath. You can debug further seeking the resolved modules with the help of --show-module-resolution.
    • Naman
      Naman over 5 years
      Just wondering how are you creating the artifact from IntelliJ. I am unable to do that for a intelliJ JavaFX project. Is your project based on maven/gradle by any chance?
    • DrMorteza
      DrMorteza over 5 years
    • Med Dhia Saadlaui
      Med Dhia Saadlaui over 5 years
    • Naman
      Naman over 5 years
      Not really sure what you're trying to do in the last step, but that's certainly not the way to execute a Main class as to what I know. I would suggest you to follow the getting started guide according to your project structure and framework.
  • DrMorteza
    DrMorteza over 5 years
    Thanks a a lot. This solved the issue: set PATH_TO_FX="C:\Program Files\Java\javafx-sdk-11.0.1\lib"
  • José Pereda
    José Pereda over 5 years
    Yes, I figured that out from your question, but took the opportunity to explain how to use Artifacts to do the (semi) fat jar and the possible issues you may find in the process.
  • DrMorteza
    DrMorteza over 5 years
    Yes. You made a full useful guide. As you said, I have to try jlink. I think it's a new good feature in Java world. Thanks again José
  • Domenico
    Domenico over 4 years
    Thanks a lot. I spent the last two hours trying to build my JavaFX application in a executable jar, but i was missing the Launcher class step.
  • profPlum
    profPlum over 3 years
    I don't see the native libraries in the jfx-sdk I got from here: gluonhq.com/products/javafx How can I make the fat jar using this SDK?