I am running java version 11.0.2 on a Mac. WHen I compiled a java file that imports javafx.util.pair I got an error: package javafx.util does not exist. There are not many useful resources to solve this issue. I tried different suggestions online, but in no vain. Currently I am trying to add the JavaFX package to my Java directory. But it doesn't work.
Here is what I did:
Downloaded javafx-sdk-11.0.2 folder. Inside the folder, there are 2 directories - legal and lib
Moved items in legal dir to /Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home/legal
Move items in lib dir to /Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home/lib
Reopen Terminal to compile this .java file.
Question_1: Did I miss anything above?
Question_2: If this approach is wrong, what would you suggest?
javafx.util.Pair is part of the javafx.base module, and as you have mentioned, you need to download the JavaFX SDK to your machine, as it is no longer part of the Java JDK anymore.
You can follow the OpenJFX docs on how you can get started.
Once you have downloaded the SDK, if you want to run JavaFX 11, you will see that you need to do something as documented:
export PATH_TO_FX=path/to/javafx-sdk-11.0.2/lib
javac --module-path $PATH_TO_FX --add-modules=javafx.controls HelloFX.java
java --module-path $PATH_TO_FX --add-modules=javafx.controls HelloFX
This means that you run your Java 11 and include the modules from the JavaFX SDK independent location. Note that javafx.controls has as transitive dependencies the javafx.base and the javafx.graphics modules.
However, you won't read in those docs that you have to copy the JavaFX files into the JDK. That won't work.
The main reason why it won't work: Java 11 and JavaFX 11 are modular, and even if you see the JavaFX jars under path/to/javafx-sdk-11.0.2/lib, the JDK uses a big file: /path/to/jdk-11.0.2.jdk/Contents/Home/lib/modules to run the java command. That file was created when the JDK was built, therefore adding any jar to it won't have any effect.
Alternative
However, you will find in the docs the right way to "copy" the JavaFX SDK into the JDK: by creating a new custom image. See the link, section Custom JDK+JavaFX image.
You can use jlink to create a runtime image that includes some or all the JavaFX modules, without being attached to a given project.
So you can create a combined image Java11+JavaFX11, and use that as your new JDK. This will allow you getting rid of the --module-path and --add-modules arguments (in terms of JavaFX at least).
In fact, some distributions like this one already do this.
So the options are: you use the regular JDK and the JavaFX SDK (with --module-path and --add-modules) or you create/use a custom JDK that includes JavaFX.
Related
I created a javafx application via the IDE IntelliJ IDEA on ArchLinux. Now, I want to start this program without any IDE, so I created a .jar file. When trying to start the program with java -jar myprogram.jar, then I get the error message that runtime components for javafx are missing. Fine - I'll add these with the --module-path option, and it runs.
However, this --module-path thing only works somehow when I set the module path being somewhere in /lib/... On the other hand, when I try to copy the javafx modules into the folder where the myprogram.jar file is and set the module path there, the modules cannot be found.
My issue is the fact that I want to "self-contain" everything possible in one folder, such that I could copy&paste everything on another machine where the JVM is installed and just run it, and do not want to depend on the specific path where the javafx modules are installed. Maybe there is another way than to customize the --module-path?
Any help? Thanks :-)
Forget about trying to create a single executable jar that includes JavaFX components and depends on a pre-installed JVM (it is not a supported configuration).
However, cwellm's answer here details a method that keeps the modular JavaFX dependencies separate from the created application jar by keeping the JavaFX modules in separate jars added to the module path, I believe that this might be a valid and supported deployment configuration. It does require deploying multiple jar files to the client in the right locations in order for it to work. Another alternative would be to assume a distribution of the JDK such as liberica or corretto which can come with JavaFX included in the base JDK distribution, then you don't need to specify a module path for JavaFX as it will already be present in the default boot module path for the JDK.
Recommended Solutions
Instead create a runtime image using jlink, this can be done by (among other methods) using the openjfx maven plugin.
Or if you want an installer, use jpackage which can also (among other methods) be created using maven, see JPackageScriptFX as an example.
jpackage doesn’t create archlinux native packages. So if you want that, then jpackage wouldn’t be the thing to use. Instead you could use a maven assembly or tar call to create a zip or tar.gz of the jlink output, or use the pacman tool to create a native archlinux package of the same.
Or if you like gradle see the badass jlink and runtime plugins.
Using a build tool (maven or gradle) to include the JavaFX dependencies rather than relying a JavaFX sdk download is preferred IMO. Also, if possible, define a module-info. Then jlink can be used to create the required runtime from your app, it’s dependencies and the jre, as well as the execution script for the app, so that things are self-contained. Native packages in rpm or deb format created by jpackage takes this further. Installing apps packaged this way also ensures all required OS lib dependencies are correct.
If you want to understand more see the contextual info (FAQ section) in this answer:
How to create a standalone .exe in Java (that runs without an installer and a JRE)
It is possible to put several custom module paths into the command --module-path. It is important to really put in the full path of the required modules, including the filename of the module itself. For instance, let's assume I want to include the modules module1.jar and module2.jar for the execution of MyApplication.jar, and all of these files are put into the same folder, say /my/custom/folder. Then the command line command would look like this:
java -jar --module-path /my/custom/folder/module1.jar:/my/custom/folder/module2.jar --add-modules module1,module2 MyApplication.jar
I've packaged a JavaFx (14) project with jpackage for deployment in .exe setup.
The project dependencies are:
Java 14.0.2
JavaFx 14.0.2.1
JRE 1.8.0_271 (removed)
So, during my deployment on several machines (approximately 6), it was successful on several, but on others I have this error:
JVM can not launch
although all the dependencies have been properly installed on these machines as well as the environment variables well defined.
Can someone help me about it
After some fixes (mentionned by #Slaw and #mipa, I generated a new package, install it. But when I run the software (myApp.exe), I've this error
Failed to lunch JVM
After some research about it, the solution was to create a batch file with java command that will run the .jar file located on the C:\Program Files\ software folder
cd "C:\Program Files\software\app"
java --module-path "C:\Program Files\Java\javafx-sdk-14.0.2.1\lib" --add-modules=ALL-MODULE-PATH --add-exports javafx.graphics/com.sun.javafx.sg.prism=ALL-UNNAMED -jar software.jar
I've done it and it run the software very well, but is there another optimize solution to run directly the software without the batch file?
Cause on some computers, the batch didn't run the software, returning that same error: Failed to lunch JVM
Please, help
If you have to manually launch the application with --module-path and --add-modules then you failed to include JavaFX while packaging the application, or at least failed to include JavaFX correctly. Keep in mind that JavaFX is modular, even if your code is not. So when you package your application you should tell jpackage to treat JavaFX as modules.
First, you should get the JavaFX JMOD files. You can get them in one of at least two ways:
Download the JMOD files from Gluon (the same place you downloaded the JavaFX SDK from).
Install and use a JDK that includes JavaFX (e.g. from Zulu Community, BellSoft Liberica, etc.).
With this option you don't need the JavaFX SDK to begin with.
You want the JMOD files because they package the native code (and other things, such as licenses) with the Java code. This allows jlink (used behind-the-scenes by jpackage) to gracefully include the native code with the custom run-time image. Also, don't forget that JavaFX (and by extension the JMOD files) is platform-specific. And jpackage can only create applications for the operating system it's invoked on.
After getting the JMOD files you'll want to package your application. Let's assume your code is not modular (you use -jar in your question) and you've packaged your code into a JAR file. The following command should be the minimum you need to use jpackage:
jpackage --type app-image --module-path <path-to-jmods> --add-modules <needed-modules>
--input <dir-containing-your-jar-file> --main-jar <your-jar-file>
--main-class <your-main-class> --dest <your-output-location>
Some notes:
If you install and use a JDK with JavaFX included then you won't need --module-path. At least not for JavaFX.
I'm not sure what modules your application needs (for the --add-modules option). You use ALL-MODULE-PATH but I doubt you need everything.
Not positive, but I believe if you have a Main-Class attribute in your JAR file's manifest then --main-class is not needed.
If you truly need the --add-exports argument then you can use:
--java-options="--add-exports javafx.graphics/com.sun.javafx.sg.prism=ALL-UNNAMED"
If you make your code modular you can also get rid of the --add-modules argument. Instead you'd put your module (and any modules not in the JDK) on the --module-path and replace --input, --main-jar, and --main-class with --module-path and --module.
In this case --input no longer seems necessary. However, if you had other files needed by your application (e.g. security policy files) then you may still need --input.
See the JPackage User Guide for more information. There are many ways to customize your application described in the guide that are not mentioned in this answer.
If all this still doesn't solve the "Failed to launch JVM" error on every computer then you're going to need to do further debugging. The first thing you want is to know the actual error causing the problem. I can think of at least two ways to do this:
Add logging to your application. Log to a file.
Configure jpackage to make your application console-based. Then launch the application from the console to see any output. If you're having issues seeing the output then you can redirect the standard/error streams to a file or use options that tell the console not to open a new window.
The program based on JDK 9(JPMS), using some third party jars like Apache (poi-3.17.jar, commons-io-2.6.jar ) & HikariCP (HikariCP-3.1.0.jar) , when using the IDE(Intellij) I "requires" them and the program works fine .
When I try get my customeized JRE using java9 'jlink' I get the following :
/out$ jlink --module-path production --add-modules
studyModule,java.base,java.datatransfer,java.desktop,java.logging,
java.scripting,java.sql,java.xml,java.prefs,javafx.base,
javafx.controls,javafx.fxml,javafx.graphics,javafx.media,
javafx.swing,javafx.web,jdk.jsobject,jdk.xml.dom,jdk.unsupported
--output studyJre
Error: module-info.class not found for com.zaxxer.hikari module
/out$ jlink --module-path production --add-modules
studyModule,java.base,java.datatransfer,java.desktop,java.logging,
java.scripting,java.sql,java.xml,java.prefs,javafx.base,
javafx.controls,javafx.fxml,javafx.graphics,javafx.media,
javafx.swing,javafx.web,jdk.jsobject,jdk.xml.dom,jdk.unsupported
--output studyJre
Error: module-info.class not found for poi module
questions is : why those packages with the IDE works fine ? if they not been moduleized then should not work in the IDE as well .
P.S : I added those jars to the "root" folder when working with jlink.
Remember that jlink is a non-standard tool and it does not have to follow exactly the same rules as classic Java. One of its differences is that it requires all modules to be explicit (i.e. have module-info.class). Automatic modules are not supported. If you want to make a custom runtime image, you have to convert all automatic modules to explicit ones. See, for example, this question to know how to achieve it.
I have Ubuntu Linux system with Sun JDE 9.0.1 and I need to convert some of Fx's CSS files to binary form from console.
But when I execute the command:
javapackager -createbss -outdir . -srcdir .
I got an error:
Error: jfxrt.jar needs to be on classpath for -createbss and for
-createJar without -nocss2bin
My JDK is properly installed. I have all necessary modules (including FX).
Any ideas how I can avoid a stupid bug and I make the packager to do it's job?
If I run javapackager from "/usr/lib/jvm/java-9-oracle/jmods" directory it completes without error. So right now I am using an ugly fix, search the modules directory, make it current, run packager from there. But that's damn ugly.
javapackager doesn't accept any other parameters but outdir, srcdir and srcfiles so I can't force loading or looking path for the jfx module. But may there is some trick with environment variables or something that can make the fix less ugly?
P.S. Running from jmod directory or removing "-srcdir" from the parameters eliminates the error, but the packager doesn't generate any output files (even if I specify input files with "-srcfiles"). Seems as javapackager is completely broken in createbss mode. Does anyone use it with Java 9?
I've checked the sources - javapackager from JDK 9.0.1 is totally broken! Use executable file from Java 8. I filled out a bug report to Oracle and all of a sudden they were very surprised (nobody noticed that one of the basic function ot a core tool is broken yet?!).
TEMPORARY SOLUTION: Use the javapackaged tool from JDK 1.8. All you need is the executable itself and you can put at any place. I put it right into my project tree (under "tools" directory) and call from a building script. WARNING! Use this replaced executable for "createbss" ONLY! Use the regular one for all other things!
I created a small application which includes an external package called JavaFX. The package contains 4 jar file.
When I create a jar from the command line to the current directory, the jar executes OK (importing classes from the 4 jars). But when I move that jar file from a different directory, the file wont execute. In other words the created jar can't seem to locate the classes in those jar files (JavaFX jars) ?
Below is the manifest file:
Main-Class: QuizMenu
Class-Path:
deploy.jar
javaws.jar
jfxrt.jar
plugin.jar
The textfile does contain a space at the start and end of each line of the jars, and a final carriage return at the last line (Each line apart from the last line does not contain a carriage return). Also the Main-Class: header works OK. (Just the classpath doesn't seem to work).
Can anyone identify the problem with the file?
Recommendation
You should not refer to any of these (deploy.jar javaws.jar jfxrt.jar plugin.jar)
jar files in your mainifest file.
JavaFX Packaging Tools
Instead, you should use JavaFX aware deployment tools such as:
javafxpackager
JavaFX ant tasks
JavaFX maven plugin
JavaFX gradle plugin
NetBeans JavaFX project
Some other compatible tool which might come along in the future.
The above tools will appropriately package your application to use JavaFX.
Background
If you try to bundle the JavaFX, Java deployment and Java plugin jar files with your application, then when you run your application on a different Java version (such as Java 8 or 9), it may not function correctly as JavaFX in all future releases will be defined to be part of the Java runtime platform and not as a separately installed library or a library which can be bundled with an application separate from the rest of the Java runtime.
Additionally, jar files such a jfxrt.jar rely on numerous native dynamically linked libraries (.so, .dll, etc) which differ from platform to platform and have 32 bit and 64 bit variants. The version of jfxrt.jar must match the version of the underlying native libraries (and the underlying native libraries for the appropriate platform must be available to the dynamic load linker) in order for jfxrt.jar (e.g. JavaFX) to function correctly.