问题
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.
回答1:
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
回答2:
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
finalize()
is called before Garbage collector reclaim the Object. JVM does not guaranty when this method will be invoked.finalize()
gets called only once by GC thread if object revives itself from finalize method than finalize will not be called again.In your application, you may have some live objects, on which garbage collection is never invoked.
Any Exception is thrown by finalize method is ignored by GC thread
System.runFinalization(true)
andRuntime.getRuntime().runFinalization(true)
methods increase the probability of invokingfinalize()
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:
- The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
- 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.
- 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.
- 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
Do not depend on
finalize()
orshutdown hooks
to release critical resources in your application.use
try{} catch{} finally{}
blocks appropriately and release critical resources infinally(}
block. During release of resources infinally{}
block, catchException
andThrowable
.
来源:https://stackoverflow.com/questions/20829228/shutdown-hook-vs-finalizer-method