Reputation: 1133
In searching for a JRE to run my (javafx-based) desktop application I found JRE version 8 from here https://www.java.com/en/download/manual.jsp . This is the default, and this is where I am redirected when clicking the JRE link on Oracle's website (https://www.oracle.com/downloads/#category-java)
But, the JRE does not support --module-path
obviously because it's too old.
What are my options for running my app on non-developer machines? (note the JRE is 60MB and the JDK is 190MB).
I am afraid to ask why the default JRE download is too old?
My app compiles with openjdk 17.0.9 2023-10-17
Upvotes: 1
Views: 950
Reputation: 15196
You should try using jlink to make a compatible JRE from a JDK. Before using jlink, verify that the JDK you want to base the JRE on can run your application using appropriate class-path / module-path entries.
If that works, try to generate a JRE that just contains the modules you use such as JavaFX. For example:
set JAVAFX_MODS=C:\java\javafx-jmods-21
jlink --module-path "%JAVAFX_MODS%" --add-modules javafx.base,javafx.controls,javafx.graphics --strip-debug --no-man-pages --no-header-files --output jre-fx
This means that you can use jre-fx\bin\java
to launch any class that uses JavaFX without specifying JavaFX modules again.
Later, you could also use jlink
to make a JRE with your own module, if you have correct dependences on JavaFX and set the module-path, the new JRE will contain everything needed to run your application:
jlink --module-path "%JAVAFX_MODS%;your-module-dir" --add-modules yourmodule --strip-debug --no-man-pages --no-header-files --output jre-all
With this new JRE - jre-all\bin\java
- you only need to specific the launch class names, all modules are included.
If you need to distribute your application for other machines then look at jpackage to build installers - EXE/MSI on Windows or other packager for Mac/Linux. It can be setup to use your pre-generated JRE with jpackage --runtime-image jre-all
or it can use jlink
internally for you each time it is launched.
Upvotes: 2
Reputation: 1133
The answer by @BasilBourque lists the options for downloading JRE which supports latest java features and understand the --add-modules
features. This is the accepted answer to my question.
However, I will outline here the whole process of packaging my app and its dependencies because, for my case, jlink kept complaining that it did not find basic dependencies, see comments under @DuncG 's answer.
I have also placed a demo at https://github.com/hadjiprocopis/javafx-uberjar
Create CLASSPATH, MODULEPATH and MODULES for your app. If you are using maven this is easy by parsing the output of mvn -X javafx:run@dry-run-cli
to create said vars.
Collect the dependencies (jars) somehow. To me, it does not sound logical to download all these dependencies when I have maven which downloaded already these in its repository (located at ~/.m2/repository/...
). So, I resorted to the spring-boot
maven plugin which creates a JAR with all dependencies plus my app classes. This JAR warns with WARNING: Unsupported JavaFX configuration: classes were loaded from 'unnamed module ...'
and I did not trust it to distribute it. In any event, this jar file now contains all the dependent jars in its lib/*
. As a bonus it can contain OS-specific javafx jars for any other OSes you specify in the pom.xml
as a <dependency>
with <classifier>
set to linux,win,mac
, etc.
The structure of the distribution zip/tar-ball will be:
a. lib
dir to contain all 3rd-party jar dependencies, even module jars, even OS-specific jars e.g. javafx-media-22-ea+11-mac.jar
, javafx-media-22-ea+11-win.jar
, etc.
b. classes
dir to contain your apps classes or a jar.
c. launchers
dir to contain launcher scripts for your target OS(es).
The launcher script will in general be something like:
java -classpath "classes:lib/xyz.jar:..." --module-path "lib/javafx...jar:lib/..." --add-modules "javafx.base,..." com.myapp.Main
Note that in M$ the classpath separator ':' should be ';'
Now the last and biggest problem is to find a JRE which provides a java
command which understands --module-path
et.al. (which were introduced with java v9+). What prompted me to ask this question was the fact that oracle provides a JRE (via www.java.com) which supports java version 8!!!!! (When currently on java version 20 and counting). The oracle obviously knows all, so I will not dispute this decision. The fact is, that I am jreless after all this hard work.
All people answering this question (thank you all for your effort) suggested to create my own JRE using jlink
. That did not work for me. It complains that it does not find basic dependency like java.base
(using openJDK v17 on Linux Fedora installed via its package manager from package java-17-openjdk-devel : OpenJDK 17 Development Environment
). In addition, the lame example hellofx
assumes that my app is a module, which it isn't. Additionally, maven javafx:jlink
fails as well (for me) with various dependencies not found. It is a mystery because maven compile javafx:run
runs without problems.
Since creating my own JRE is not working for me, I resorted to downloading a JRE supplied by https://adoptium.net/en-GB/temurin/releases/ (I think it is associated with Eclipse). Is it safe? Is it "official"? I have no idea.
The answer by @Basil Bourque lists a few more options. (And actually is the accepted answer)
I have placed a demo at https://github.com/hadjiprocopis/javafx-uberjar
it runs on linux and can create a distribution zip archive for linux, mac and/or the unnamed-os.
It relies on your app being developed as a maven project because all the dependencies are collected via maven and spring-boot plugin. All the javafx depdendencies will be read from the local maven repository it uses for compiling and running your app. There is no need for you to download any third-party dependencies and keep parallel versions!
thanks for the help (but no thanks :))
Upvotes: 1
Reputation: 340070
Two vendors provide editions of their JDK/JRE products for Java 17, 21, and current 22 bundled with the modern generation of OpenJFX libraries implementing JavaFX: Azul Systems and BellSoft.
Understand that JavaFX has never been a standard part of Java.
And understand that JavaFX is now implemented in the open-source project OpenJFX. That project is under continual active development, co-led by Oracle Corp and the Gluon company.
Years ago, Oracle chose to bundle JavaFX libraries with some of its JDK/JRE products. Then later they stopped bundling.
Oracle is but one of several vendors offering JDK/JRE products. See Java Is Still Free for an explanation of the Java ecosystem.
Some JDK/JRE vendors currently choose to bundle the JavaFX libraries implemented as OpenJFX in some editions of their products. I know of at least two such vendors:
The Java Platform Module System arrived in 2017 in Java 9 and later. The vendors listed above offer JavaFX-bundles for the modularized LTS versions 11, 17, and 21, as well as the current version (now 22).
JavaFX 22 requires JDK/JRE 17 or later.
Alternatively, you can bundle the OpenJFX libraries within your app. And you can bundle a JRE within your app, and optionally slim down the JRE to include only the parts that your app uses. The OpenJDK project offers tooling to assist: jlink and jpackage.
The cutting-edge technology uses GraalVM to produce a native app from your JavaFX project.
You asked:
But, the JRE does not support --module-path obviously because it's too old.
Java 9 and later has the Java Platform Module System (JPMS). Focus on the LTS versions (11, 17, 21) and current (22) as the other versions have reached EOL(End of Life). The latest versions of OpenJFX support Java 17 and later.
What are my options for running my app on non-developer machines?
If you have control over user machines, such as in an enterprise or education environment, consider having the sysadmins install a JRE that comes bundled with the necessary OpenJFX libraries.
In a niche market, perhaps you can require your users to install a JRE bundled with the OpenJFX libraries.
In a broad retail market, you’ll need to bundle both a JVM and the OpenJFX libraries within your app. The app marketplaces such as Apple App Store will accept such a product.
(note the JRE is 60MB and the JDK is 190MB).
You can greatly reduce that size by using the jlink tool with your JPMS modularized project.
I am afraid to ask why the default JRE download is too old?
The “why” is simply that Oracle later decided to stop bundling JavaFX libraries with their own JDK/JRE products.
But you are free to bundle the OpenJFX libraries within your app, at no cost.
And, you have the choice of obtaining more recent versions of Java JDK/JRE bundled with OpenJFX libraries from vendors other than Oracle. You can obtain free-of-cost products as well as products with paid support.
My app compiles with openjdk 17.0.9 2023-10-17
Then you can use OpenJFX 22 while compiling for Java 17.
Upvotes: 10