I have a simple console application which sometimes need to perform graphics operations, for those I'm using JavaFx framework (there are some functions that I need like the css styling for text ) I simply generate some shapes and text into an hidden scene then save those on file and that's all,
I know that to work with JavaFx I have to pass graphics operations to the JavaFx thread, but when everything is done and I have to close the application (after some hours) this JavaFx thread still remain open... and I really don't want to force exit with System.exit() because if something is blocked I may want to know/wait (ALSO I don't want to execute everything as an JavaFx application (as JavaFx components are less than 1% of my main application)
the code is very simple and googling around I've found only to use
Platform.exit();
which doesn't seems to work, I've also tried playing with Platform parameters like
Platform.setImplicitExit(false);
here is my test application which you can run :
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.geometry.Pos;
import javafx.scene.layout.VBox;
public class SOTestFX {
public static void main(String[] args) {
SOTestFX t = new SOTestFX();
t.runFxThread();
}
public void runFxThread(){
//Application.launch(args);
final JFXPanel jfxPanel = new JFXPanel();
Platform.runLater(new Runnable() {
@Override
public void run() {
System.err.println("CREATING IMAGE");
simpleFXoperations();
System.err.println("NOW CALL EXIT");
System.err.println("JAVA FX THREAD SHOULD BE EXITED NOW");
Platform.exit();
}
});
try {
Thread.sleep(3000); // just wait a bit if something should happen, let it happen..
} catch (InterruptedException e) {
e.printStackTrace();
}
//jfxPanel.removeNotify(); // return -> java.lang.NullPointerException
//Platform.exit(); // -> does nothing
System.err.println("i will never die!");
}
public void simpleFXoperations(){
VBox vbox1 = new VBox();
vbox1.setAlignment(Pos.BOTTOM_CENTER);
vbox1.setStyle("-fx-border-style: solid;"
+ "-fx-border-width: 1;"
+ "-fx-border-color: white");
System.err.println("simpleFXoperations() _DONE");
}
}
and this is the thread which never close
"Attach Listener" - Thread t@17 java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers: - None
"JavaFX Application Thread" - Thread t@13 java.lang.Thread.State: RUNNABLE at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at com.sun.glass.ui.gtk.GtkApplication$3$1.run(GtkApplication.java:82) at java.lang.Thread.run(Thread.java:722)
Locked ownable synchronizers: - None
Update: I'm using latest Oracle JDK 7u17 64bit on Linux Fedora 16 64bit.
That's a slippery situation, as (to my understanding) the purpose of the JavaFX thread is to take advantage of various hardware pipelines transparently. Might I suggest placing your JavaFX requests in a separate, referenced, project; and keep everything else, including your main method, in another? That's always worked for me.
Basically, business logic and model go in one project, and view and control (generally JavaFX-based) go in the other. This allows for independent termination of the JavaFX thread. Hopefully that is applicable to what you are trying to do.
Your main function does not belong to the JavaFx Application object and i think that your program never eneter application thread loop.
It seems you should do:
I tried a lot of things on this as none of the above answers worked for me. Best thing for me was to just shutdown the whole JVM using
as my whole Application is just that one JavaFX application and therefor can be shut down, when closing the Stage. The 1 in my case is just a random int.
Fix:
I was able to fix this problem by calling
com.sun.javafx.application.PlatformImpl.tkExit()
immediately beforePlatform.exit()
. I don't really understand the JavaFX source that well, but it seems to be working; YMMV.Update: Doing this in Java 8 will produce a warning, you can just turn the warning off with
@SuppressWarnings("restriction")
. It shouldn't be a problem.Explanation:
I figured this out by digging through the source code;
JFXPanel
has this little snippet (this is from JavaFX 2.2.25)The problem is, if you are using only a little bit of JavaFX in your application, then the
idle(boolean)
method never does anything (becausefirstPanelShown == false
), which prevents the listener from getting removed, which prevents the JavaFXToolkit
from shutting down... which means you have to shut it down manually.