1

When writing a JavaFX application, you can provide a shutdown hook to any javafx.stage.Stage with the setOnCloseRequest(EventHandler<WindowEvent>) method. If you do that with your main JavaFX Scene, it serves as an application shutdown hook, and can be used to safely save/release important system resources, etc. But the same (or something very similar) is achieved if you implement a java.lang.Thread and add it as a shutdown hook with Runtime.getRuntime().addShutdownHook(Thread) method.

What are the differences between those approaches. Both work if I call Platform.exit()? Both work if I call System.exit(int)? Which one is considered the safest (meaning, that better ensures saving/releasing system resources) approach? Are there better ways, other than those that I should consider?

Ramiro
  • 698
  • 6
  • 21
  • Ask yourself the question "What if I had more than one stage?"... – James_D Dec 22 '15 at 13:53
  • I understand the use of setOnCloseRequest() when I have more than one Stage. That's the reason why I specifically mentioned that if you provide a handler to you *main* Scene with setOnCloseRequest() it works like a shutdown hook. – Ramiro Dec 22 '15 at 14:04

1 Answers1

1

These are fundamentally different things.

A handler specified for a particular stage with setOnCloseRequest() will be executed when the user requests to close that particular stage (typically by pressing the OS-specific "close" button in the window). It is invoked on the FX Application Thread, and will be called before the window actually closes. It's execution does not imply that the application is exiting, that the FX toolkit is being closed down, or that the Java Virtual Machine is exiting. A handler here may not only assume the FX toolkit is still running, but may modify the UI (since it is on the FX Application Thread) and may veto the request to close the window by consuming the event.

A shutdown hook is a user-provided thread that is executed when the Java Virtual Machine exits. It is its own thread, and is executed as part of the shutdown sequence. As such, it must not assume any other services are running. From the API docs:

They should also not rely blindly upon services that may have registered their own shutdown hooks and therefore may themselves in the process of shutting down. Attempts to use other thread-based services such as the AWT event-dispatch thread, for example, may lead to deadlocks.

The same caveat that applies to the AWT event dispatch thread also applies to the FX Application Thread.

In some very specific circumstances, the invocation of a setOnCloseRequested handler may indicate that the JVM may soon be about to exit. These circumstances include all of the following, but I may have omitted something:

  1. The handler does not consume the event
  2. The stage is the last stage left open
  3. Platform.isImplicitExit() returns true
  4. No non-daemon threads are running, and none are started by the Application instance's stop() method

Which you should use depends entirely on what you are trying to do. If the aim is to release resources started as part of you JavaFX Application that are only no longer needed when the application exits, I would not use either of these, but would override the Application.stop() method.

James_D
  • 201,275
  • 16
  • 291
  • 322
  • It seems that Application.stop() Thanks for your answer. After reading the documentation, it seems that the use case for the `Runtime.addShutdownHook(Thread)` to be very unusual. Can you point out an example? – Ramiro Dec 27 '15 at 23:27
  • 1
    Typically you use a shutdown hook if you need to provide clean-up code (closing files, etc) to be executed on a system-level shutdown (e.g. for something launched from the command line, to catch a CTRL-C). This is really more applicable for server implementation code than for a GUI application. I have very rarely used this (so my answer is not definitive); one case where I did use it was a stand-alone (non-GUI) Spring application where I needed to close the application context to make sure resources it created were properly closed down. (Recent Spring versions have better ways to handle this.) – James_D Dec 27 '15 at 23:36