I have a publicly available Java 8 desktop application complete with MSI installer that I'd like to update to Java 17.
The current user experience goes like this:
- User downloads MSI installer and runs it
- MSI installer checks for compatible Java 8 VM, if not present prompts the user to install one from http://java.com.
- User launches
application.exe
which is a shim that basically runsjava jar application.jar
.
What I'm struggling to understand is what the user is expected to install in a Java 9 world. If I send the user to for example: https://www.oracle.com/java/technologies/downloads/ they are greeted with downloading the Java Development Kit which is a confusing thing to install for a user ("Is this right? I don't want to develop stuff??").
In addition when you land on http://java.com it says "if you were asked to download java, it's most likely this", which implies that if you release applications you should either use Java 8 (and forget the JavaFX disaster that is OpenJDK pre version 11, and just use Orcale Java)...
I was under the impression that after Java 9, the promise of Jigsaw was to build a package that contains a native runtime and jar, all neatly bundled together so that the days of the end user having to install a JVM were over. However searching online, I see no support for this is Gradle or IntelliJ (or Eclipse for the matter) so this seems kind of like a dead pipedream?
If I want to ship a Java 17 application, is the user expected to install the JDK? If not, how am I supposed to package and ship my application?
CodePudding user response:
Oracle's point of view:
- There is no longer a JRE (SOURCE: Try to find a JRE that oracle offers you above version 8 - it doesn't exist).
- Instead, you write your app with modules, and use the jlink tool to make a 'tree shaken' JVM, this is a JVM with all the stuff that the modules you are using as basis don't even need. You produce one JVM for each and every platform you are interested in exporting as stand-alone installer thing.
- You then write an installer that installs the tree-shaken JVM, and your app, somewhere. The tree shaken JVM is not registered as 'system JVM', in fact that notion that there is a JVM installed on a PC and you can find it using e.g. registry keys or by looking in known places such as
C:\Program Files\JavaSoft
is obsolete. You don't do that, that JVM is only for that app, that app knows where to find it and nothing else on the system does. Each and every java-based app has its own copy of its own (tree shaken or not) JVM that only it uses. - You, as the 'vendor', are on the hook for maintenance. If the JVM you shipped has a gaping security hole in it and that gets abused, it's your fault for not updating it, not oracle's. Oracle does not run
jusched.exe
or any other tooling to ensure it is kept up to date.
An easy alternative to this is that you simply move the responsibility of having a java runtime that can run your app to the shoulders of your user. Tell THEM to go download a JDK (because a JDK can run java apps just as well, actually better, than a JRE can), tell THEM to ensure it's on the $PATH
or in a known location / tells you where to find it / set JAVA_HOME
, and they are responsible for keeping it up to date.
Other vendors' point of view:
- Various other vendors do make a JRE for more modern versions. I have no idea if these JREs ship with
jusched.exe
or other update mechanisms, and how (or even if) these JREs register their existence in a way that your app / your installer can figure out where they are. You'd have to investigate.
There is no need to actually treeshake a JVM, you can also just ship a full blown JDK with your app. For example, if your installer ends up doing this:
- Sets 'program install root' ('root') to
C:\Program Files\EmilysAwesomeGame
- Unpacks JDK17 for windows x64 into
ROOT\jdk
. - Unpacks all your dependency jars into
ROOT\lib
. - Unpacks your main app into
ROOT\emilygame.jar
- Makes a
.BAT
file that runs%~dp0\jdk\home\bin\java -jar %~dp0\emilygame.jar
and that jar has a MANIFEST with aClass-Path
entry containing e.g.lib\javafx.jar lib\someotherdep.jar
, then.. that'll work fine, and replacing that bat file with an exe that does the same thing also works fine (and 'ship your own JVM in a subdir' is a model that tools like launch4j and similar have supported for a long time already).
The downside of not treeshaking is that the JDK is pretty large, and includes all sorts of stuff you wouldn't be using. But, it's just a matter of saving on disk space, a non-treeshaken JDK isn't going to run any slower, those unused parts would simply end up never being loaded.
A very common 'deployment model' is that you offer an msi with an exe for windows-x86 and tell everybody else to go install a JDK on their own responsibility and ship plain jars for everybody else (linux users, mac users, windows-aarch64, etc).
CodePudding user response:
This question gets asked over and over again. Therefore there is an extensive diskussion of this topic here on SO. See: https://stackoverflow.com/tags/javafx/info The most relevant part for you is the section about "Packaging".