Thanks to the persistence of an evaluation user, we have discovered that JavaFX 2 apps can be run without the custom classloader and hence can be fully precompiled with the current version of Excelsior JET! There are a few quirks in the build process, as you will see, and we have not extensively tested it, but the four standard demos seem to be working, at least on Windows.
Here is one of the demos, by the way:
JavaFX 2.2.1 Ensemble Demo
Download (19.1 MB)
Note: That’s 19.1 MB for a self-contained package, i.e. a single installer that depends on neither the JRE nor the JavaFX Runtime. That is at least a quarter slashed off the download sizes and nearly half off the disk footprints (proof), not to mention the complexity of installing two or three packages instead of one.
And here is how you can test Excelsior JET against your standalone JavaFX app:
First, verify that your app can be launched directly on HotSpot:
- Make sure you have a 32-bit Oracle JRE 6 and a 32-bit JavaFX 2.2 Runtime installed on your system.
- In the directory containing your JavaFX app jar, create a batch file called e.g.
jfxhs.batand paste the following commands into it:
@echo off rem rem jfxhs.bat - Run a JavaFX app using the standard Java classloaders. rem set JAVA_HOME=C:\Program Files (x86)\Java\jre6 set JAVAFX_HOME=C:\Program Files (x86)\Oracle\JavaFX 2.2 Runtime "%JAVA_HOME%\bin\java.exe" ^ -cp "%JAVAFX_HOME%\lib\jfxrt.jar;%1" ^ "-Djava.library.path=%JAVAFX_HOME%\bin" ^ %2
If needed, change
JAVAFX_HOMEto point to the locations of the 32-bit JRE and JavaFX runtime on your system.
Now try launching your app as follows:
jfxhs JavaFX-app-jar JavaFX-app-class
JavaFX-app-jaris the name of the jar file containing your JavaFX application and
JavaFX-app-classis the name of the class specified in the
JavaFX-Application-Class:line in that jar’s manifest.
For instance, the following command will run the
jfxhs Ensemble.jar ensemble.Ensemble2
If your JavaFX application starts and works correctly when launched this way, you are good to go. Here is how you can natively compile and package it with Excelsior JET:
Create a copy of the
jfxjet.bat, and edit it so that
JAVA_HOMEpoints to the
jresubdirectory of the current Excelsior JET profile, e.g.:
. . . set JAVA_HOME=C:\jet7.6-ent\profile1.6.0_34\jre . . .
then run it with the same arguments:
jfxjet JavaFX-app-jar JavaFX-app-class
Instead of your app window, you should see the JET Control Panel splash, followed by a Create Project dialog:
Clicking Proceed will take you to the Start page, with all necessary information already in place.
- Try running your application on the Excelsior JVM. Go to the Test Run page and click Run. (Compared to the Oracle JRE, it will take your app way more time to start and the app will feel sluggish, but that is normal.) If the app seems to be working okay, close it and proceed to the next step, otherwise see Troubleshooting below.
- On the Target page, set Stack trace support to “Minimal” (“Full” will also work.)
- On the Compile page, click Build to compile your JavaFX application into a native executable. Upon successful build, click Run to confirm that your app works when natively compiled, and then click Package to switch over to the JetPackII tool that will help you create a self-contained installation package.
The first JetPackII page displayed will be the Files page, with your freshly compiled JavaFX executable and the required components of Excelsior JET Runtime already added to the package. JetPackII is not JavaFX aware, though, so you need to add all DLLs from
%JAVAFX_HOME%\binto the package manually. You can place them right into the root of the package, or create a subdirectory, say,
- On the Resources page, the
java.library.pathproperty in the Java system properties pane will still point to the
binsubdirectory of the JavaFX Runtime installed on your local system. Correct that property to point to the JavaFX DLLs you have just added to the package, e.g. “
- On the Trial Run page, skip the trial run. (It won’t work because of a missing environment variable – see below for details and workaround.)
- Build the package and try deploying it to systems that do not have Java nor JavaFX installed.
- MOST IMPORTANT: Let us know if it worked! 🙂
Once you have a working build, make a backup of the project files and try tweaking some settings. In particular, the Global Optimizer and Java Runtime Slim-Down have worked without any issues in our limited tests — the above JavaFX Ensemble demo binary was built with these enabled.
If your application fails during the Test Run in the JET Control Panel:
On the Classpath page, check that your application jar(s) and
jfxrt.jarfrom the JavaFX runtime are included into classpath.
On the Start page, check that the Application Main Class field contains the main class of your application, not the default
com/javafx/main/Main. That is the class specified in the
JavaFX-Application-Class:line in the manifest file of your application jar.
If your application has passed the Test Run, but the executable produced by Excelsior JET fails, check whether stack trace support is completely disabled on the Target page. It should be set to “Minimal” or “Full”.
Finally, if your application works on the system on which it was compiled, but fails when installed on another system, open the respective JetPackII project, go to the Resources page and double check that:
You have added all DLLs from
%JAVAFX_HOME%\binto the package, and
The system property
java.library.pathpoints to that location, e.g.
Beware of typos!
- On the Classpath page, you may set the Pack into exe property to “auto-detect” for all jars.
Some of the DLLs in
%JAVAFX_HOME%\binare only needed when a JavaFX app is launched as an applet or via Java Web Start and need not be included in the installation package. We have had no time yet to prepare a “safe-to-omit” list of JavaFX DLLs.
The reason Trial Run fails for JavaFX apps is that JetPackII tries to simulate a system where neither Excelsior JET nor Java are installed, and in doing so passes only the absolutely essential environment variables to the application. But one of the native libraries in the JavaFX runtime relies on certain files in the directory to which the
CommonProgramFilesvariable points, and the entire app terminates abnormally if that variable is not set or points to a wrong location.
The workaround is to wrap the application in batch file that would set that variable back. Just note that you need to set
CommonProgramFiles(x86)on 64-bit systems.
Add to your package a batch file named e.g.
trialrun.batwith the following contents:
SET CommonProgramFiles=C:\Program Files\Common Files SET CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files %1
Add a new Trial Run scenario, specifying
trialrun.batas the executable, and the (relative) name of the actual application executable as the argument. (Note that root substitution does not work in the Arguments field.)
- Add to your package a batch file named e.g.
If you have any questions, or just want to confirm whether you were able to natively compile your JavaFX apps, please feel free to post comments or email us.
Appendix: Download Size and Disk Footprint Comparison
|JRE 7||two||32.9 MB||133.3 MB|
|JRE 6+JavaFX Runtime||three||23.6 MB||133.2 MB|
|Excelsior JET||one||19.1 MB||72.6 MB|
Ensemble.jar is 8.5 MB uncompressed, but that can be brought down to 3.2 MB with pack200 and 7-Zip.
Offline Oracle JRE 6u34 installer for 32-bit Windows weighs 16.2 MB and the JavaFX 2.2.1 Runtime installer for the same platform is 7.4 MB. Together that is 23.6 MB. (The latest JRE 7 includes JavaFX, but for some reason its size is whopping 29.7 MB, even though the disk footprint difference is minimal.)
Categories: Excelsior JET