When I wrote my last article about ways to avoid runtime components errors,it got me thinking: if you want to test the version of JavaFX, regardless of how your project is set up, how do you go about doing it?

After all the searching, the simple answer is it depends on the version of Java you’re using and the situation in which you’ve deployed your app, but there are a few good guiding principles.

The current JavaFX version can be determined by requesting the system property “javafx.runtime.version” using System.getProperty(String key). Prior to Java 11, this can also be determined using the JavaFX-specific VersionInfo.getRuntimeVersion().

In certain circumstances, such as in WebStart apps and Applets, accessing system properties is forbidden by the Java SecurityManager. In this case, the version should be obtained manually from the filesystem through the javafx.properties file of javafx.base.

Let’s go through each in turn, starting with why the version is important – and how to get the version in each of the scenarios above.

Why is the JavaFX version important?

The point of separating JavaFX from the Java Standard Edition was to accelerate its development. That means more bug fixes and extra features can be rolled out from the JavaFX open source community according to a schedule they dictate. JavaFX 14 mostly involved bug fixes and a few minor enhancements and optimisations. But the added stability will be a springboard for extra development.

Equally, Java 1.8, which included JavaFX, is under long term support until at least 2030. I’ve worked in at least one company where Java 1.8 and 1.7 were installed on machines because of other legacy software requirements. In case you’re wondering, yes, each JRE has a different version of JavaFX.

All that adds up to two things:

  1. When you’re trying to deploy your application, you want to be able to test which version of JavaFX you’re hooking into if you’re using the system’s JRE, and
  2. If you’re using jlink, which is designed to package your software with a custom JRE, you might want to test the JavaFX version to test whether your build process has proceeded as planned.

How can I check the JavaFX version?

There are 3 ways to check the version(s) of JavaFX you have on your machine:

  • Use the JavaFX-specific VersionInfo.getRuntimeVersion() method
  • Request the version using System.getProperty(String key)
  • Manually verify the version using the javafx.properties file.

If you have multiple versions of Java on your machine and you need to map which versions may be accessible, you will need to manually parse the available versions in point 3.

Let’s dive into each in turn.

1. Programatically checking the JavaFX version

The most useful information to get regardless of whats available on the machine, is which version of JavaFX is your program currently running. In Java 1.7 and 1.8, we an use the JavaFX class VersionInfo. From Java 9 onward, this is not available.

Java 1.7 and 1.8

To get the version of JavaFX that your application is currently using, we can access VersionInfo‘s static methods getVersion() and getRuntimeVersion() from anywhere in our program.

public class Main extends Application {

    @Override
    public void start(Stage stage) throws IOException {
        System.out.println(("JavaFX Version: " + VersionInfo.getVersion()));
        System.out.println(("JavaFX Runtime Version: " + VersionInfo.getRuntimeVersion()));
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Both methods will retrieve information about the version of JavaFX present on the machine. The getRuntimeVersion() method provides additional information about project milestones (for example it will flag beta-version builds) and build numbers.

Output: for Java 1.8.0:

JavaFX Version: 8.0.261
JavaFX Runtime Version: 8.0.261-b12

JavaFX versions were increasingly synchronised with the Java version through Java 1.8. If you’re interested in how these versions changed, checkout the table below.

Java 9 and onwards

Since Java modules were introduced, strengthening encapsulation of packages inside modules, the JavaFX-specific VersionInfo class cannot be accessed outside of javafx.base. If you try to, you’ll get hit with an error:

java.lang.IllegalAccessError: class com.edencoding.Main (in module com.edencoding) cannot access class com.sun.javafx.runtime.VersionInfo (in module javafx.base) because module javafx.base does not export com.sun.javafx.runtime to module com.edencoding

Specifically, that means that the package com.sun.javafx.runtime is protected inside javafx.base – and can’t be accessed by us. So we’ll need to use something else if we’re using a modular build.

Luckily, the VersionInfo class (which we can’t access) runs a method that transfers all of its properties into the System properties (which we can):

public static synchronized void setupSystemProperties() {
    if (System.getProperty("javafx.version") == null) {
        System.setProperty("javafx.version", getVersion());
        System.setProperty("javafx.runtime.version", getRuntimeVersion());
    }
}

We can access all of these properties through System.getProperty(String key). In this case, the properties we’re looking for are javafx.version and javafx.runtime.version.

public class Main extends Application {

    @Override
    public void start(Stage stage) throws IOException {

        System.out.println("JavaFX Version: " + System.getProperty("javafx.version"));
        System.out.println("JavaFX Runtime Version: " + System.getProperty("javafx.runtime.version"));
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Here, I’ve run this code with OpenJDK 14 and JavaFX 13. The output is:

JavaFX Version: 13
JavaFX Runtime Version: 13+14

Can System.getProperty throw an Error?

System.getProperty() is useful, but it can go wrong for a number of reasons. Potential pitfalls are:

  • A SecurityException is thrown.
  • getProperty(String key) returns a null value

Below is the code inside the System class associated with getting properties. I’ve included the code for the checkKey(key) method, because it demonstrates other ways the getProperty() method can throw exceptions. But, for the purpose of this tutorial, I’m going to assume you’re not passing getProperty() a value that is null or an empty String. I’ll just assume you’re passing it a sensible String like "javafx.version".

I’ve highlighted the parts of the code that will throw the SecurityException.

public static String getProperty(String key) {
    checkKey(key);
    SecurityManager sm = getSecurityManager();
    if (sm != null) {
        sm.checkPropertyAccess(key);
    }

    return props.getProperty(key);
}

private static void checkKey(String key) {
    if (key == null) {
        throw new NullPointerException("key can't be null");
    }
    if (key.isEmpty()) {
        throw new IllegalArgumentException("key can't be empty");
    }
}

1. A SecurityException is thrown.

Here, the important part is the SecurityManager.

If a SecurityManager is present, the very first thing getProperty() does is to check whether you’re allowed to access that property. If you’r not allowed, the SecurityManager will throw an AccessControlException – a type of SecurityException.

This is most likely with WebStart and Applet technologies. While they’re decreasing in popularity, if you’re encountering this exception, it may be worth looking at signing your jar.

2. getProperty(String key) returns a null value

All properties in the System class are contained in a map of key-value pairs. It’s actually a bit more complicated than that, with a Properties object that can that has a “default property” layer underneath the set properties. Nonetheless, in the case of a returned null value, the simple explanation for this is that props.getProperty(key) works out that no property of that name exists.

If you’d like to specify a default value yourself in cases where the key is not found, you can do that with System.getProperty(String key, String default).

Checking JavaFX Version Directly in the filesystem

If all else fails, digging around in your file-system is a good fail-safe way to check the version of JavaFX you have available. You can do this for versions of JavaFX that are bundled with the JRE, as well as for more modern versions of JavaFX that are provided separately.

1. Bundled with JRE

If you have versions of JavaFX that are bundled with the JRE, the JavaFX runtime image (jfxrt.jar) can be found by

  1. Navigating to the JDK folder in your filesystem
  2. Navigating to the JRE folder, and then inside the lib directory
  3. Open the javafx.properties file in a text editor

Here’s the contents of javafx.properties for Java version 1.8.0_261:

javafx.runtime.version=8.0.261
javafx.runtime.build=b12

If you want to, you can confirm this is exactly what’s hard-coded into the JavaFX runtime by delving into the JavaFX jar jfxrt.jar itself. You’ll need to extract jfxrt.jar using either a tool like 7Zip, or by using the jar tool that Oracle provide.

The jar is in the same directory as the javafx.properties file. You can find the VersionInfo.class by following the structure down a few layers:

C:\ProgramFiles\Java\jdk\jre\lib
├── javafx.properties
├── jfxrt.jar/
│   ├── ...
│   ├── javafx/
│   │   ├── animation/
│   │   ├── ...
│   │   ├── runtime/
│   │   │   ├── ...
│   │   │   ├── VersionInfo.class

2. Not bundled with Java

Here, we don’t need to navigate through the JDK and JRE, we just need to find the jar we either downloaded, or that our build framework downloaded for us.

In this case, we can find both the javafx.properties file and the VersionInfo class in the javafx.base jar.

javafx-base.jar
├── javafx.properties
├── com/
│   ├── sun/
│   │   ├── javafx/
│   │   │   ├── ...
│   │   │   ├── runtime/
│   │   │   │   ├── VersionInfo.class

This is the contents of the javafx.properties file in my OpenJFX javafx.base-13-win.jar:

javafx.version=13
javafx.runtime.version=13+14
javafx.runtime.build=14

Using your IDE

In the case of either bundled or separate JavaFX runtimes, accessing the internals of the jar is made significantly easier by IDEs. These often highlight the libraries in use, allowing you to browse through them.

Here, in IntelliJ, even when the runtime is downloaded by Maven, we can easily find the javafx.properties file at the root of javafx-base-13-win.jar.

Alternatively, we can browse through the file structure of the JavaFX base jar to determine the version in the VersionInfo class.

The VersionInfo class in javafx.base can be used to determine the version of javafx in use.

Relationship between Java and JavaFX versions (before Java 11)

Once you start digging around in the JavaFX versions, it can get a little confusing. So, if you’re getting curious about why the versions of JavaFX don’t match up between Java 1.7 and Java 1.8, we can tie them together here.

A tiny bit of history

JavaFX started life as “JavaFX Script”, which was a scripting language that compiled to java bytecode. Come Java 1.7, JavaFX was included on the class path for the first time. Then, over the course of Java 1.7 and 1.8, the JavaFX version was increasingly synchronised with the Java version it was shipped with.

Version alignment

In Java 1.7, JavaFX 2.2 gradually aligned build numbers with Java. From Java 8, JavaFX jumped to version 8 and versions were synchronised with the Java runtime.

Java VersionJavaFX Version
1.7.0_062.2.0
1.7.0_072.2.1
1.7.0_082.2.2
1.7.0_092.2.3
1.7.0_10 to 1.7.0_122.2.4
1.7.0_132.2.5
1.7.0_172.2.7
1.7.0_21 and onwardsBuild number aligned with Java
e.g. 1.7.0_X e.g. 2.2.X
1.8.0 versionsJavaFX bumped to Version 8.
Build and minor version aligned with Java
e.g. 1.8.X_Y e.g. 8.X.Y
Java 9 versionsJavaFX Version 9
Versions aligned with Java versions
Java 10 versionsJavaFX Version 10
Versions aligned with Java versions

Conclusions

Methods for identifying the version of JavaFX can depend on the version of JavaFX you’re using. For version of JavaFX shipped with JREs for Java versions 1.7 to 1.8, the JavaFX class VersionInfo can be used to determine the JavaFX version.

For later versions of JavaFX, this class is not available, and the version should be looked up in the system properties using the method System.getProperty(). This can return null in cases where a property of the specified name cannot be found.

In certain circumstances, the version of JavaFX cannot be obtained by using System.getProperty(). In these cases, the version can be manually determined from the JavaFX properties file in the filesystem.