shutdown hook vs finalizer method
Asked Answered
M

2

13

I just fail to understand why must one use Runtime.addShutdownHook. If you want to do some cleanup when the jvm exits, why not just overload the finalize method of the daemon class. What is the advantage of using shutdown hook over finalize method.

Also there is a deprecated function runFinalizersOnExit. If I set it to false, I believe finalizers won't run. This contradicts the java guarantee that finalizers always run before garbage collections.

Moniz answered 29/12, 2013 at 19:29 Comment(1)
"This contradicts the java guarantee that finalizers always run before garbage collections." ... Java guarantee? There is no such guarantee. This method was created for simpler times when multicore processors were not the norm and when concurrency was less common, but now ... it is wildly unsafe and can potentially lead to irreversible system corruption. Nobody should ever use runFinalizersOnExit.Chick
C
23

There is no guarantee that a finalizer will ever run. finalize() is called when the object is garbage collected. But the garbage collector may not collect anything when the program runs.

Shutdown hooks by contrast are run when the jvm exits normally. so even that isn't 100% guarantee either but it's pretty close. There are only a few edge cases where a shutdown hook doesn't run.

EDIT I looked up the edge cases where a shutdown hook is not executed

Shutdown hook IS executed:

  • When all of JVM threads have completed execution
  • Because of call to System.exit()
  • Because user hit CNTRL-C
  • System level shutdown or User Log-Off

Shutdown hook IS NOT executed:

  • If the VM crashes due to an error in native code then no guarantee can be made about whether or not the hooks will be run.
  • If JVM is killed using -kill command on Linux or Terminate Process on windows, then JVM exits instantly
Coed answered 29/12, 2013 at 19:40 Comment(5)
If i recall correctly, only for threads with daemon status, the finalize function will definitely not run. Could you please reason,why finalize may not run for normal threads. Also what are the edge cases where the shutdown hook won't run during graceful shutdownMoniz
@SKr Thread objects may not be GC'd after the actual thread ends if the VM exits right away, for example.Drucie
@Drucie if you meant abrupt shutdown of jvm, in that case even shutdown hook won't executeMoniz
@SKr No, I wastalking about normal shutdown. Last thread ends -> VM exits. No GC. No finalizers.Drucie
@SKr updated answer with when shutdown hooks are run and are not runCoed
P
5

Regarding your query

If you want to do some cleanup when the jvm exits, why not just overload the finalize method of the daemon class

I have found good information from this article

  1. finalize() is called before Garbage collector reclaim the Object. JVM does not guaranty when this method will be invoked.

  2. finalize() gets called only once by GC thread if object revives itself from finalize method than finalize will not be called again.

  3. In your application, you may have some live objects, on which garbage collection is never invoked.

  4. Any Exception is thrown by finalize method is ignored by GC thread

  5. System.runFinalization(true) and Runtime.getRuntime().runFinalization(true) methods increase the probability of invoking finalize() method but now these two methods have been deprecated. These methods are very dangerous due to lack of thread safety and possible deadlock creation.

Coming back to shutdownHooks, as per oracle documentation

public void addShutdownHook(Thread hook) Registers a new virtual-machine shutdown hook.

The Java virtual machine shuts down in response to two kinds of events:

  1. The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
  2. The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
  3. When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently. When all the hooks have finished it will then run all uninvoked finalizers if finalization-on-exit has been enabled.
  4. Finally, the virtual machine will halt. Note that daemon threads will continue to run during the shutdown sequence, as will non-daemon threads if shutdown was initiated by invoking the exit method.

But even oracle documentation quoteed that

Shutdown hooks should also finish their work quickly. When a program invokes exit the expectation is that the virtual machine will promptly shut down and exit.

In rare circumstances the virtual machine may abort, that is, stop running without shutting down cleanly

Considering drawbacks of the both these approaches, you should follow below approach

  1. Do not depend on finalize() or shutdown hooks to release critical resources in your application.

  2. use try{} catch{} finally{} blocks appropriately and release critical resources in finally(} block. During release of resources in finally{} block, catch Exception and Throwable.

Pyrognostics answered 26/12, 2015 at 14:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.