3

I have an executable jar file compiled with Java 8 and containing a JavaFX application called app.jar.

When I had Java 8 installed I could run it simply with java -jar app.jar.

Now I only have Java 11 installed and running the command above generates the following error:

Error: Could not find or load main class <...>
Caused by: java.lang.NoClassDefFoundError: javafx/application/Application

because Java 11 no longer includes JavaFX.

So I looked into installing JavaFX. openjfx.org provides JavaFx in two forms: an SDK and in JMOD files.

I figure I don't need the SDK because I am not creating a JavaFX but merely running one. This leaves the JMOD files as the remaining options.

However, the Oracle documentation on JMODs says: "The JMOD file format let’s you aggregate files other than .class files, metadata, and resources. This format is transportable but not executable, which means that you can use it during compile time or link time but not at run time," so it does not seem like they are going to help me running an application.

Questions:

  • How can I run app.jar as defined above with a Java 11 runtime?
  • Is there any documentation explaining how to do this and, if so, where?
user118967
  • 4,895
  • 5
  • 33
  • 54
  • I don't think you can run a Java8 jar using Java9+. Java8 is not modular. Java9+ are. – SedJ601 Oct 26 '20 at 23:30
  • 1
    @Sedrick You can. They specifically created the concept of the "unnamed module" to allow pre-module/non-modular code to run on Java 9+. – Slaw Oct 27 '20 at 01:00
  • 2
    The JMOD files are only for compile-time and link-time (i.e. `jlink`); you can't use them at run-time. You either want the SDK or download a JRE distribution that contains JavaFX (there are a couple out there). If you choose the latter then JavaFX applications run the same as before. If you choose the former then you'll want something like `java --module-path -jar app.jar` for a non-modular application. Note if you create a run-time image (`jlink`) then you'll want to use the JMOD files as they handle native code better than the JARs from Maven Central. – Slaw Oct 27 '20 at 01:07
  • 1
    As Slaw notes, it is likely the steps to [Run HelloWorld using JavaFX](https://openjfx.io/openjfx-docs/#install-javafx) coupled with [how to run a jar file](https://stackoverflow.com/questions/1238145/how-to-run-a-jar-file), e.g. it is the same if you were to run a class file from the command line, except you add the `-jar` to the `java` command and you need to provide the modules (because they aren't in the openjfx distribution) and set the module-path correctly. – jewelsea Oct 27 '20 at 02:17
  • 1
    Alternately perhaps try a [Liberica Java distribution](https://bell-sw.com/pages/downloads/#/java-15-current) if that is an option. I think Liberica includes JavaFX out of the box, so perhaps your jar would then run on it without having to separately supply the JavaFX modules and add a path to them. Looks like Liberica is a JDK, not a JRE, so it is wouldn't be the correct solution for everybody. – jewelsea Oct 27 '20 at 02:20
  • 1
    Sorry, I missed something in the command line example I gave. It should actually look something like this: `java --module-path --add-modules -jar app.jar`. Where `` is the directory containing the JavaFX modules (the JAR files) and `` is the JavaFX modules you need for the application (typically at least `javafx.controls`, which will pull in `javafx.graphics` and `javafx.base` implicitly, but may also include the other modules e.g. `javafx.media`, where each module name is separated by a comma). – Slaw Oct 27 '20 at 07:55
  • 1
    But you should consider making your application modular and then using `jlink` and/or `jpackage` (Java 14+) to create a self-contained application. The latter even makes your application appear as a native executable that just so happens to use Java/JavaFX "behind-the-scenes". Both options also mean you don't have to worry about your end users having the correct versions of Java or JavaFX installed, if they're installed at all. – Slaw Oct 27 '20 at 08:16
  • 1
    Even if you correctly do everything that was mentioned so far it is not guaranteed that your app will work because there were several incompatible changes in JavaFX between 8 and 11. Depending on whether any of these changed APIs were used in your code this may work or not. So, be warned and not be too dissapointed if does not work. – mipa Oct 27 '20 at 09:29
  • 1
    @Slaw In order to use jpackage/jlink it is not necessary to modularize the application. – mipa Oct 27 '20 at 11:19
  • Thanks, for clearing that up all! – SedJ601 Oct 27 '20 at 22:45
  • @mipa True, but if you can I would still suggest making the code modular. Also, that's only true with `jpackage`. With `jlink` you may not have to _personally_ make your code (or dependencies) modular but the "workarounds" I've seen all _convert_ the non-modular code into modular code. That's because `jlink` only works with modules. Whereas `jpackage` is capable of configuring the class-path instead of (or in addition to, I believe) the module-path. – Slaw Oct 28 '20 at 21:13
  • @Slaw I only mentioned this to make it clear that you can use a combination of jdep/jlink/jpackage even if your application is not fully modular. In this tutorial we show how that can work https://github.com/dlemmermann/JPackageScriptFX – mipa Oct 29 '20 at 09:48

1 Answers1

0

Seems like you've missed adding the PATH_TO_FX environment variable to your system. You can find a guide on how to do that here:

If it's a Java 8 application, easiest option for you is simply getting Oracle JDK 8 and defining that as the JDK in system environment.