JRE, the concept, is obsolete - JRE1.8 was the last one. Various vendors (such as Azul) make JREs for newer versions, but it's no longer a supported deployment platform.
Hence, no wonder your end user has it installed. JRE1.8 is no longer supported and is very old, certainly too old to run what you compiled, which you compiled on the very newest java version.
You can tell your java to produce code that is JDK8 compatible with javac --release 8 *.java
for example (or check your build tool docs for how to tell it to add this parameter), but it means you can't use any API introduced since then (and lots has been introduced), nor any java language feature introduced since then (so, no var
, no record
, no """
strings, etcetera).
But, your deployment model is obsolete!
Your deployment model is:
- You, end user, arrange for a JRE to exist. All I can do is tell you to go download one someplace.
- I shall ship you a jar file.
- You double click it.
This model is no longer recommended or available. Finding a JRE is now quite difficult and it is not reasonable to expect users to have it. At best you can ship extensive documentation about where they can get one (not openjdk.org or java.com, not anymore!)
There's a reason for that: It really never worked well, oracle/team OpenJDK's choice to get rid of the JRE vs JDK distribution model is perhaps more them just waking up and realizing how the real world has been deploying java apps, rather than that they are trying to annoy you by changing how things work.
The new model involves you shipping the java runtime together with your app and you taking on the responsibility of maintaining it.
There's various tutorials out there on how to do this, jlink
is a key part of it (so include that in your searches). Alternatively, and this isn't particularly hard either, as this was already quite popular even 10 years ago when the JRE deployment model was still a thing: You can ship an entire JDK with your jars and make a simple installer. Things like launch4j exist that make it real easy for your users to launch it (simply click the EXE).
The problem with the JRE deployment model in a nutshell:
- Your end users would 'contract' with oracle to download a JRE, install it on their system, and oracle+user would work together to keep it up to date. Failure to do this (for example, users getting jusched.exe out of their system start up folder) means oracle catches the heat for having a JRE that is probably insecure (due to not being updated).
- All you could really do as app vendor is tell the user they need to go to oracle.com or java.com or whatnot first. This was awkward.
- You have no real guarantee that the JRE they do have is compatible. Java is mostly backwards compatible but it can easily happen that, say, your app does not run on java 10 but it does on java8. If someone installs a JRE10, then your app 'runs' and crashes. It is very difficult to test your app on JRE8,9,10,11,12,13,14,15,16,17,18, and 19, so people didn't, and this led to apps failing all the time.
- Because it's a system thing, the JRE needs to announce where it is at, and register itself as being the thing to use to run any
.jar
file. This makes the security situation considerably more tricky.
Contrast to the new model (which is the model lots of folks already used before this became the official model, because of the issues with the old model listed above):
- You deploy precisely the JDK/JRE you want, and tested with.
- There is no need to inform the user about needing to go to java.com
- There is no need for this JDK/JRE to announce itself to the system.
- There is less need to keep it updated; given that it doesn't register itself to run
.jar
files or otherwise gets involved in being executed for anything, other than your app, and most JDK security issues cannot be exploited unless the app is 'in on it' / can be fixed app-side.
- It matches what the major java apps, such as intellij and eclipse, were already doing.
The downside of this new model is that it's a lot more effort to write an installer. One advantage of JREs, that they are smaller in size, can be reproduced with jlink
that, amongst other things, can make a tree-shaken JDK (a JDK with all parts that your specific app does not need, taken out of it).