Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to stop "JavaFX Application Thread"

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.

like image 257
Francesco Avatar asked Apr 04 '13 09:04

Francesco


People also ask

What is JavaFX application thread?

JavaFX uses a single-threaded rendering design, meaning only a single thread can render anything on the screen, and that is the JavaFX application thread. In fact, only the JavaFX application thread is allowed to make any changes to the JavaFX Scene Graph in general.

What does platform exit do?

It's generally recommended that you exit a JavaFX Application with a call to Platform. exit() , which allows for a graceful shutdown: for example if there is any "cleanup" code you need, you can put it in the stop() method and Platform. exit() will allow it to be executed.

Which JavaFX application lifecycle method the application shuts down?

Terminating the JavaFX Application When the last window of the application is closed, the JavaFX application is terminated implicitly. You can turn this behavior off bypassing the Boolean value “False” to the static method setImplicitExit() (should be called from a static context).

Is JavaFX thread safe?

The JavaFX scene graph, which represents the graphical user interface of a JavaFX application, is not thread-safe and can only be accessed and modified from the UI thread also known as the JavaFX Application thread.


2 Answers

Fix:

I was able to fix this problem by calling com.sun.javafx.application.PlatformImpl.tkExit() immediately before Platform.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)

finishListener = new PlatformImpl.FinishListener() {
  public void idle(boolean paramAnonymousBoolean) {
    if (!JFXPanel.firstPanelShown) {
      return;
    }
    PlatformImpl.removeListener(JFXPanel.finishListener);
    JFXPanel.access$102(null);
    if (paramAnonymousBoolean)
      Platform.exit();
  }

  public void exitCalled()
  {
  }

The problem is, if you are using only a little bit of JavaFX in your application, then the idle(boolean) method never does anything (because firstPanelShown == false), which prevents the listener from getting removed, which prevents the JavaFX Toolkit from shutting down... which means you have to shut it down manually.

like image 165
durron597 Avatar answered Oct 11 '22 10:10

durron597


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:

public class SOTestFX extends Application {
    public static void main(String[] args) {
        launch(args);
    }
    @Override
    public void start(Stage stage) throws Exception {
        // Do stuff here to show your stage or whatever you want;
        // This will be called on the JavaFX thread
    }
}
like image 28
LeonidVlad Avatar answered Oct 11 '22 12:10

LeonidVlad