What is the JavaFX runtime? - java

In the documentation it is often said that 'the JavaFX runtime' is doing XY in the background - but what is "the runtime"?
If I understand correct (please edit) the runtime is made of the following parts:
all classes etc. of the JavaFX framework, located in package javafx and stored in the jxfrt.jar file
the 'JavaFX-Launcher' thread
the 'JavaFX Appliaction Thread': all Objects and threads running your JavaFX application. They are created by the JavaFX-Launcher thread when the Appplication.launch() method was called.
My question is: What is the runtime?

J Woodchucks answer addresses Java 7 and 8. This answer just addresses Java 9+.
For JRE 9+, jfxrt.jar does not exist and is replaced by .jmods in the <JRE_HOME>/jmods directory. This was done as part of JDK modularization. Additional required native libraries for JavaFX are included in the <JRE_HOME>/lib directory. JavaFX will not work without the required native libraries.
You can use the full JRE runtime provided by a vendor such as Oracle (and probably a third party OpenJDK provider such as an Ubuntu or Redhat JRE package). This will include all required modules and libraries to run JavaFX as well as some that form part of the JRE but are not necessarily required to run a JavaFX application.
Note, for Java 8, some OpenJDK vendors chose not to include the JavaFX runtime as part of their Java distributions, requiring either an install of an additional package a custom build of the OpenJDK or a switch to a java runtime which does include JavaFX (such as the Oracle JRE). Hopefully, for Java 9, all OpenJDK vendors will provide full JRE runtimes that include JavaFX but you might need to wait until the OpenJDK vendors release generally available Java 9 runtimes to find out.
It is possible to create a custom modular runtime for JavaFX with Java 9 which eliminates some JRE modules that your application may not need. A custom modular runtime for JavaFX requires the javafx.* modules that you wish to use, any dependent modules of those modules and any necessary native libraries. You can package your JavaFX application with a custom runtime using the JavaFX packager. The packaging technique of the JDK 9 javafxpackager is based upon the Java 9 module system; the internal implementation of which uses the java linker.
The java packager can further package the custom runtime as part of a self-contained application install package (if desired). A self-contained application contains your Java or JavaFX application and the JRE needed to run the application.
Once Java 9 undergoes its general availability release, I am sure that Oracle will provide some further official documentation and samples that demonstrates how to create a custom modular runtime for a JavaFX application and use it as part of a self-contained application.
Additionally, third party vendors such as gluon provide tools to package applications with custom JavaFX runtimes on various devices such as iPads and Android phones.

The JavaFX Runtime being referred to is the jfxrt.jar jar you mention. It contains the libraries required for JavaFX, including the JavaFX launcher thread (LauncherImpl in package com.sun.javafx.application) and Application class. The location of jfxrt.jar (whether you have the JDK or JRE) is:
For Java 7, under jre\lib
For Java 8, under jre\lib\ext
I don't see LauncherImpl documented in Oracle's javadoc, so linked to OpenJDK version above.

jewelsea's update for Java 9+ changes again with Java 11.
Java 11 does not come bundled with JavaFX: you have to get it and link it yourself.
You can in fact do this without knowing all the gory details if you use Gradle. A build.gradle file will typically contain these lines:
plugins {
...
id 'org.openjfx.javafxplugin' version '0.0.8'
}
...
javafx {
version = "13"
modules = [ 'javafx.controls', 'javafx.fxml' ... ]
}
...
The gory details for configuring a non-Gradle JavaFX project in an IDE like IntelliJ can be found here. You have to download and extract a (recent) JavaFX JDK and then include this as a library, and then as a module.
If ever you need to run at the CLI (or just to see what's happening) do this sort of thing. Assuming you have extracted a JavaFX JDK 11 from here to a directory (created by you) such as ~/.java/JavaFX. And assuming you have a class in package sample, called Main, which extends javafx.application.Application:
java -cp .:~/.java/JavaFX/javafx-sdk-11.0.2/lib/*.jar --module-path ~/.java/JavaFX/javafx-sdk-11.0.2/lib --add-modules javafx.controls,javafx.fxml sample.Main
... looks complicated but in fact it's quite simple: you configure the classpath with the current directory and all the .jars in the library ... but you also have to specify that this is a module path, and then say which modules you need. NB Windows will need the other slash, and elements in the classpath separated by ";" rather than ":", of course.

Related

Can't integrate SWT with JavaFX under "Zulu" JDK 11

We want to use both SWT and JavaFX in an Eclipse plugin within our RCP application. Unfortunately, we're experiencing problems integrating SWT with JavaFX under Java 11. The build environment uses e(fx)clipse 3.5. We're developing against the Community edition of Azul Systems' "Zulu" JDK 11, bundled with Azul's version of OpenJFX.
Formerly, we developed under Java 8. At that point, our build used a compile-time class path referring to jfxswt.jar, which lived in the jre/lib directory of the JDK. We didn't use any special class path settings at run-time.
We are now trying to move to Java 11. There, this JAR has become javafx-swt.jar and lives in the lib directory of the JDK. It no longer seems to be enough to set the class path to refer to this JAR at compile time: it seems to be necessary to do so at run time too. If we don't do this, we get an error (java.lang.NoClassDefFoundError: javafx/embed/swt/FXCanvas).
As a test, we experimentally embedded javafx-swt.jar within the JAR implementing our Eclipse plugin. We then referred to it in that plugin's .classpath file, and the code worked as expected. Unfortunately, we can't embed the JAR this way for legal and other reasons.
A note on Java modules: javafx.swt does not show up in the output when we issue the --list-module command. We tried running the application using parameters -p /path/to/JDK/lib/javafx-swt.jar --add-modules javafx.swt, but this doesn't seem to solve the problem.
My question: Is there a way to set up the class or module path to allow our Eclipse plugin to find this library in the JRE? Any solution would have to work with whatever JRE the code happens to be run against (I think it is all right to assume lib/javafx-swt.jar will live in that JRE).
Would it help to use a separately-downloaded version of OpenJFX rather than the copy of OpenJFX in our JDK?
Very many thanks ☺

Bundle JavaFX app with openjdk 11 + runtime

I've created a small HelloWorld Java app that relies on OpenJDK 11 and JavaFX. The app is packaged in a jar file which can only be run if I have installed Java 11 and JavaFX on my system separately.
Now I'd like to convert my jar into a self-contained Java application which includes JavaFX and a fully-functional Java runtime environment. This will allow me to run my app without installing OpenJDK 11 (which presents technical hurdles such as setting PATH correctly etc).
I can find information about creating self-contained Java applications on Java 10 but I cannot find information about bundling a Java app with OpenJDK 11 and JavaFX.
How can I ship a self-contained Java app (which includes a java runtime) with OpenJDK 11 and JavaFX?
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.
OpenJFX, the open-source development of JavaFX, is a part of the OpenJDK project. OpenJFX may or may not be included in a build of OpenJDK. The Java specifications do not require JavaFX functionality.
At least two vendors provide an edition of their JDK product that comes bundled with the OpenJFX libraries:
ZuluFX from Azul Systems
LibericaFX from BellSoft
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.
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.
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
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.
(Using jdk14)
Starting by the fact that in order to use jlink your main jar should be a module.
How? Consider that you have a maven project. You just need to include module-info.java inside src/main/java dir and make sure that you require the modules that your app needs and you export the package that contains your main class. In most cases you will get a compile-time error when missing a requires. Have in mind that non-modular dependencies become automatic modules.
You can use maven's copy-dependencies to make sure that all dependencies are copied under target/lib during mvn package.
next step: jlink
Since jlink maven plugin is still in alpha, you can use command-line.
NOTES:
jlink will create a self-contained bundle directory that contains
main app module
app dependencies
jdk required modules
app launcher (optional)
jlink bundle targets one platform at a time. By default it is the current platform.
javafx runtime modules are also platform-specific. But since they are not part of the jdk we need to always provide the module-path containing them.
javafx runtime modules can be downloaded from web, or from maven repo by using the corresponding target platform classifier (win/linux/mac).
jlink can also create cross-platform bundles. Just include the target platform modules to the --module-path (e.g. from linux: download windows jdk/ javafx and add their jmods dirs to module-path).
jlink command
Case 1: build and target platforms are the same
NOTE: /path-to/javafx-mods needs to be provided to your modulepath unless you copy the required javafx deps under lib/ using maven (copy-dependencies).
jlink --launcher run=jdk14Example/com.example.javafx.app.Main \
--module-path ./lib:javafx-jdk14-example-1.0.0.jar:/path-to/javafx-mods \
--add-modules=jdk14Example --output app-bundle
Case 2: build and target platforms are differrent
# Building from linux for windows
jlink --launcher run=jdk14Example/com.example.javafx.app.Main \
--module-path ./lib:javafx-jdk14-example-1.0.0.jar:/path-to/jdk-win/jmods:/path-to/javafx-mods-win \
--add-modules=jdk14Example --output app-bundle
Conclusion:
In both of the above cases you get a directory with a self-contained application which can run on a workstation with no java/javafx installed.
# if jlink targeted linux
app-bundle/bin/run
# if jlink targeted windows
app-bundle/bin/run.bat
# if jlink targeted mac
app-bundle/bin/run

How do I use JavaFX 11 in Eclipse?

I have some trouble with JavaFX. I wanted to start creating apps, desktop or mobile, at least something. So I found out I could use the JavaFX library for it. But as far as I understood, it was excluded from JDK 9. I'm actually using OpenJDK 11 on Ubuntu 18 (though Eclipse writes I have the JavaSE 10 environment, that is where I'm also a bit confused) and I installed OpenJFX using sudo apt install openjfx and I can't make Eclipse work with JavaFX.
I'm not sure if there's any sense not to use JDK 8 with the included JavaFX, but anyway, how can I use JavaFX in such conditions in Eclipse?
There are multiple points in your post which needs clarification. I will try to answer them in different bullet points:
But as far as I understood, it(JavaFX) was excluded from JDK 9.
JavaFX will be decoupled from Oracle JDK starting JDK 11. I stress on Oracle JDK because JavaFX was never a part of OpenJDK. Not even in OpenJDK 8.
I'm actually using OpenJDK 11 on Ubuntu 18 (Though eclipse writes I have JavaSE 10 environment, that is where I'm also a bit confused)
For Java 11 support in Eclipse, you need to install
Java 11 Support for Eclipse Photon plugin.
Here are a few Examples on how to run Java 11 applications in Eclipse
I installed openjfx using sudo apt install openjfx and I can't make eclipse work with JavaFX.
I'm not sure if there's any sense not to use JDK 8 with included JavaFX, but anyway, how can I use JavaFX in such conditions in eclipse?
Since OpenJDK 11 or Oracle JDK 11 will not come bundled with JavaFX, your best bet is to either download the JavaFX SDK from here or here and load them in your IDE.
If you are used to build tools, you can directly use the JavaFX runtime jars which are available in Maven Central.
For a tutorial on how to run JavaFX 11 on OpenJDK 11, you can follow:
Getting Started with JavaFX 11
JavaFX on JDK 11
JavaFX 11 and Eclipse
At the time of writing this post, you need Eclipse 4.9M3 to work with JavaFX 11.
Once you have eclipse, JDK 11 and JavaFX 11 SDK, you can either opt to create:
Module based project
Non-module based project (No module-info.java required)
Module based Project
Create a Java project and add JavaFX jars from the Java FX 11 SDK to the module path of the project.
Create a module.info and declare its dependency of javafx.controls module. javafx11 is the name of the package which contains your Java file.
module javafx11 {
requires javafx.controls;
exports javafx11;
}
Run the program \o/
Non-module based Project
Create a Java project and add JavaFX jars from the Java FX 11 SDK to either the module-path or classpath of the project.
Add the following JVM args to the run configuration of the project:
--module-path=path-to-javafx-skd/lib --add-modules=javafx.controls
Run the program \o/
tl;dr
To most easily get started with JavaFX, use the Oracle-branded release of Java 8 where JavaFX 8 is bundled and easily available.
For technical details, see Using JavaFX in JRE 8. Look to the Linked and Related sections of the web page for many related postings.
Java Modularization
The Java platform is in the process of a sweeping reformulation, known as modularization.
Previously, Java SE (standard edition) was one big monolith of software, ever-growing with more and more being added. No single app ever uses all of it.
A decision was taken to break Java SE into many separate chunks to be defined formally as “modules”. One major benefit is that an app may be bundled with a Java SE runtime composed of only the modules actually needed, with unused modules omitted. See the jlink tool.
As a byproduct of this modularization, some older and less-popular parts such as CORBA are being dropped, to no longer be carried as a standard part of Java (though offered for other parties to pick up if they so decide). Similarly, some Java EE related modules will be removed from Java SE and turned over to the Jakarta EE project, logically a more appropriate home. See JEP 320: Remove the Java EE and CORBA Modules.
The process of modularization and reorganization is a years-long ongoing effort. Much was done in Java 9 and Java 10. Some of the final steps are being done in Java 11.
One of these steps being taken in Java 11 is to cease bundling JavaFX with Java SE. See:
The Future work section of the JavaFX Wikipedia page
The 2018-03 Oracle blog post, The Future of JavaFX and Other Java Client Roadmap Updates
The 2018-03 Oracle white paper, Java Client Roadmap Update
The curse, May you live in interesting times
So getting started with JavaFX development right now will be easiest if done with Java 8. The JavaFX libraries are bundled in with Java 8. And you need not learn about modularization, nor need to wrestle your IDE (such as Eclipse) and project settings to recognize modules. If you do not have a pressing need to use the very last versions of Java or JavaFX, stick with 8 until the modularization process and tools gets smoothed out, likely next year 2019.
If you insist on using Java 11, you need to learn about:
Java modularization in general, including the module-info.java file.
Updating your IDE (Eclipse, etc.) and other tools to later versions supporting both modularization and Java 11.
Configuring modules in your build tools, such as Maven or Gradle
Configuring modules in your IDE, such as Eclipse
Downloading JavaFX modules, or using a dependency manager such as Maven to do so
Those points are too much to cover here, and have been covered in many other Questions on Stack Overflow. Besides, Java 11 has not yet been formally released.
Perhaps this article will help, How to Create a Project With JavaFX on JDK 11.
To learn much more about Java modularization, read the blog and the book, The Java Module System, by Nicolai Parlog.
I've had to struggle through this on about 20 computers now, so I made the following checklist:
[ ] download javafx11 from javafx11's website, put on desktop
[ ] create a MODULE based project
[ ] right click project, go to BUILD PATH
[ ] add the downloaded javafx.base/control/graphics as external jar files
[ ] put the files in a package (eg: my_big_package)
[ ] put the following in the module.java file:
module javafx11 {
requires javafx.controls;
exports my_big_package;
}
[ ] eat a donut from the break room
If you're not married to Eclipse and/or just trying to learn (or are a student with an unhelpful professor/TAs), BlueJ currently has JavaFX already built into it and ready to go, so no extra setup or download is necessary. Neat!

JavaFX comes with JDK 8?

I have multiple questions regarding JavaFX.
Does JavaFX come with JDK 8? Does JavaFX also require its own runtime environment?
I looked in my computer (I have JDK and JRE installed) but could not find the JavaFX. Does this mean that JavaFX has its own seperate runtime environment and development kit? If so, where can I find the download links?
If somehow it is already downloaded on my computer, how does JavaFX work? Is it similar to Swing or completely different?
Edit Jan 2020 for those who stumble upon this question: With JDK 11, JavaFX is standalone; see jewelsea's answer below. Antonio Raposo's answer applies for JDK 8, but note that it is outdated.
JavaFX is bundled with JRE 8 and JDK 8. The JavaFX jar is jfxrt.jar and resides in the ext folder.
To deploy an application the only requisite is that the JRE 8 is properly installed.
There are similarities between JavaFX and Swing, but also differences. The best way to start is by reading the documentation available at the JDK site. Be careful to read JavaFX 8 pages and not JavaFX 2 pages as there are some differences and some old examples might not work.
You may also be interestes in one or other example I am posting in my blog A Cup of Java
Update Jan 2020
JDK 8 versions of JavaFX are now outdated.
Modern JavaFX versions (11+) are currently available from:
https://openjfx.io/ - documentation
https://gluonhq.com/products/javafx/ - hosted downloads
JavaFX libraries are usually not shipped standard with most OpenJDK or Oracle JDK versions. Instead JavaFX is available as a seperate set of libraries, modules and a SDK. Instructions on including JavaFX with your runtime distribution and developing with JavaFX are included at the openjfx.io link above.
Liberica JDK distributions by BellSoft currently ship with included JavaFX libraries and SDK tools. Or you can choose an OpenJDK version which does not include JavaFX from https://adoptopenjdk.net/ and add on a JavaFX distribution via following installation instructions at https://openjfx.io/ or as a maven or gradle dependency (also documented at the openjfx.io link).
JavaFX 8 tutorials hosted at Oracle are high quality and still relevant for use with later JavaFX versions.
Original Answer for JDK 8
JavaFX for Oracle Java 8 is not a separate installation. JavaFX is included in Oracle JDK 8 running on OS X, Linux x86 and Windows. The best place to learn more about this is the Oracle Client Technologies documentation for JavaFX.
Oracle used to distribute a binary version for Linux ARM as well, but I think that is only available by compiling the OpenJDK source now.
OpenJDK 8 binary installations, such as those which ship with Ubuntu, don't currently include JavaFX by default. For Ubuntu, it seems you can install a separate apt package for JavaFX. A user commented on another answer that the command for this is: sudo apt-get install openjfx (though I haven't an installation of Ubuntu to try it on). For more information on the relationship of OpenJDK and JavaFX, read: JavaFX and OpenJDK.
One thing that may be confusing you is that a very early version of JavaFX (1.x) was distributed as a separate download and development kit and implemented a new language called JavaFX Script which was different from Java. However, that early version of JavaFX is now no longer supported and should not be used. As of JavaFX (2.x) the JavaFX system was completely rewritten to provide a straight Java API and no longer use JavaFX Script. As of Java 8, JavaFX was completely integrated into Oracle JDK and no longer distributed as a separate download by Oracle. Being a Java API for Java GUIs that is part of the Oracle JDK, JavaFX is similar (in that way) to Swing; so the Oracle JDK provides alternate and distinct toolkits in the form of Swing and JavaFX.

Is there any way I can get a program that relies on Java7 and JavaFX2 to run "portably"?

I'm writing a program with Java7 and JavaFX2, but I'll need to show it to people who only have access to machines with Java 6 installed (with no JavaFX).
Is there any way I can find a solution to this short of asking them to install Java7 and JavaFX2?
Perhaps you can create a self-contained application package by "bundling" your program with Java 7 and JavaFX 2. That way you don't have to worry about what's on or not on your user's machine.
You can read more about self-contained application packaging at http://docs.oracle.com/javafx/2/deployment/self-contained-packaging.htm.
Theoretically yes, but you have to check if that is conform to the license conditions of Sun/Oracle the owner of JavaFX:
You could sue tools like http://one-jar.sourceforge.net/
They pack all your java into one jar.
Another possibility you could obfuscate your application and include JavaFX.
But this, too might violate the license conditions.
Both solutions might be more work, than the effort off installing JavaFX to the (one)clients computer.
Try JavaFX2 for JavaSE6
On page: http://www.oracle.com/technetwork/java/javafx/downloads/index.html
Download Download JavaFX 2.2.3 for Java SE 6 ...
If you are using Eclipse JDT, you can configure your projects "Java Compiler", by "Enable project specific settings", to "Compiler compliance level" value 1.6. This should produce bytecode in a version suitable for Java 1.6 VM. I suppose, but am not sure, that Eclipse shall also warn you if you use library elements not present in the 1.6 library version; though you can be careful about that with or without warnings. As with the previous solutions, JavaFX you can just package in your application's JAR if the license agreement allows it.

Categories

Resources