问题
After reading that OpenJDK 11 will be supported long term, I decided to create a little app (using Gradle) to test a couple of things in combination with JavaFX. After some struggle, I managed to create a Hello World .jar file that opens fine.
Now I want to get to the next step: run the .jar file without having to download anything Java related beforehand, because installing OpenJDK at the moment is a small pita by having to deal with setting PATH correctly etc.
A search on bundling a OpenJDK 11 app with a Java 11 JRE doesn't return many answers. I find that curious because (as far as I understand) OpenJDK 11 is the first one to not ship with a JRE included.
So my question is: How can I ship my Java 11 app with a runtime combined?
回答1:
Modular Java, jlink, & jpackage
Follow these tutorials found at the new home for JavaFX after having been spun out of Oracle to Gluon.
You will need to write code using modular Java. Add JavaFX 11 as a dependency to your project. And use the new linking/packaging tools to bundle a subset of the JDK within your app.
Learn about:
- Java Platform Module System
- jlink (JEP 282)
- jpackage (JEP 343)
No more JRE
Oracle no longer intends for end-users to be installing a JRE or a JDK. Java Applets in a browser and Java Web Start app delivery are both being phased out, leaving the end-user with no need for a JRE. Java-based apps are expected to bundle their own Java implementation. The only folks consciously installing a JDK will be developers & server-side sysadmins.
Important:
- Understand clearly the nature of the OpenJDK project, as explained in Wikipedia.
- Know that Oracle has committed to feature-parity between its own branded Oracle JDK and the OpenJDK project. This commitment includes donations of previously-commercial features such as Flight Recorder and Mission Control.
- Read this white paper by Oracle of 2018-03, Java Client Roadmap Update
- Read the white paper Java Is Still Free, authored by key members of the Java community.
Here is a flowchart diagram that may help you finding and deciding amongst the various vendors providing a Java 11 implementation.
回答2:
You can bundle a whole JDK with your app and create a batch script to run your app using the bundled JDK. I know this approach will bloat up your release significantly, but the alternative is to ask your user to install JDK themselves, which is not trivial for non-tech savvy people. Or you can release both versions, one with JDK bundled and one without.
回答3:
Maybe you just wait a little bit until the first EA release of the new jpackager tool is available. See http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-October/056186.html
回答4:
Native Libraries
A challenge I encountered was to inform JavaFX about it's own native libraries (.dll
, .dylib
, .so
, etc). Fortunately, getting the dylibs loaded is as simple as setting the java.library.path
using System.setProperty(...)
.
Historically, setting this variable is argued/perceived as pointless in Java as it's too late for the classloader (inferior to -Djava.library.path
) and forcing it using reflection is a forbidden security violation since Java 10... fortunately, JavaFX actually honors this variable naturally without any violations or hacks and will pick it up after it's set.
// Detect the path to the currently running jar
String jarPath = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath()).getCanonicalPath();
// Fix characters that get URL encoded when calling getPath()
jarPath = URLDecoder.decode(jarPath, "UTF-8");
String parentFolder = new File(jarPath).getParent();
// If libglass.dylib is next to the jar in a folder called "/bin"
System.setProperty("java.library.path", parentFolder + "/bin");
// ... then make any javafx calls
Java Libraries
Naturally, the .jar
files need to be accessible too. I do this the same as I would any java bundle by zipping them into the distribution (making a single, large .jar
file)
These .jar
files should be consistent with all JavaFX 11 distributions and should be bundled accordingly.
javafx-swt.jar
javafx.base.jar
javafx.controls.jar
javafx.fxml.jar
javafx.graphics.jar
javafx.media.jar
javafx.swing.jar
javafx.web.jar
Java 8 Compatibility
Initial tests against Java 8 using the above technique are positive. For now, I'm using Java version detection (not included in the above example) and ONLY setting java.library.path
for Java 11 or higher. Java 8 is EOL for personal use Dec 2019 (EOL for commercial use Jan 2019) so it is important to offer compatibility as clients migrate from one LTS release to another.
来源:https://stackoverflow.com/questions/52969440/bundle-javafx-app-with-openjdk-11-runtime