Using JavaFX Application.stop() method over Shutdownhook
Asked Answered
C

1

16

So im using shutdownhook to clean up. But since its not always guaranteed that shutdownhooks thread executes, should i just push this code onto JavaFX Application Thread (method stop()), which executes every time i close my application? Code is not expensive to run. Its basically just close socket if not closed and kill processs if not killed.

Is it good practice to use Application.stop() to cleanup over ShutdownHook?

Quote from doc:

This method is called when the application should stop, and provides a convenient place to prepare for application exit and destroy resources. The implementation of this method provided by the Application class does nothing.

NOTE: This method is called on the JavaFX Application Thread.

Is this method only intended to clean up resources of UI? So far i don't see a reason using shutdownhook over stop() at all.

Cowling answered 4/3, 2017 at 16:5 Comment(0)
W
31

stop() will only be called if you exit the application via Platform.exit() (or when the last window is closed if Platform.implicitExit is true). Shutdown hooks will execute if System.exit() is called, or if the native process running the JVM is interrupted (e.g. ctrl-C on a *nix-like OS), in addition to the usual way of exiting a JavaFX Application.

Note that it appears to be important to register the shutdown hook in the main thread, before calling Application.launch().

stop() is executed on the FX Application Thread, so it is safe to access UI elements (e.g. to show "save unsaved changes" dialogs, etc). Shutdown hooks are run in a background thread, so cannot access UI elements (indeed the FX Toolkit will probably long have stopped running by that stage).

So the choice depends on the use case.

To make this a little more concrete, here's a quick test class:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class ShutdownTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        Button platformExit = new Button("Platform Exit");
        platformExit.setOnAction(e -> Platform.exit());
        Button systemExit = new Button("System Exit");
        systemExit.setOnAction(e -> System.exit(0));
        Button hang = new Button("Hang");
        hang.setOnAction(e -> {while(true);});
        HBox root = new HBox(5, platformExit, systemExit, hang);
        root.setPadding(new Insets(20));
        root.setAlignment(Pos.CENTER);
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    @Override
    public void stop() {
        System.out.println("Stop");
    }

    public static void main(String[] args) {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("Shutdown hook")));
        launch(args);
    }
}

I tested this on Mac OS X.

Exiting via the "Platform Exit" button, by closing the window, or by right-clicking on the Dock and choosing "Quit" will execute both the stop() method and the shutdown hook.

Exiting by the "System Exit" button, by forcing the process to quit from "Activity Monitor", or by killing the process by kill id from the command line, will execute the shutdown hook only. Hanging the application by pressing the "Hang" button and then right-clicking on the Dock and choosing "Force Quit" has the same result.

Exiting by sending a SIGKILL to the process (kill -9 id or kill -SIGKILL id from the command line) executes neither the stop() method nor the shutdown hook.

Wartburg answered 4/3, 2017 at 16:12 Comment(2)
Well with this answer you just made me wonder if i would ever use stop() to close some important resource at all, since i can forcefully kill my process and as i see its not called at all, same probably with crash. Thanks for the fast answer.Cowling
@TomasBisciak The vast majority of JavaFX applications will not call System.exit() (you should always favor Platform.exit()) and are not run from the command line (reducing the possibility of an interrupt), so usually stop() will suffice. But again, it depends on your use case.Wartburg

© 2022 - 2024 — McMap. All rights reserved.