关闭钩子与终结器方法
我只是不明白为什么必须使用Runner.addShutdownHook。如果你想在 jvm 退出时做一些清理,为什么不重载守护进程类的 finalize 方法。使用关闭挂钩而不是finize方法的优势是什么?
还有一个不推荐使用的函数runFinalizersOnExit。如果我将其设置为 false,我相信终结器不会运行。这与 Java 保证结尾器始终在垃圾回收之前运行相矛盾。
我只是不明白为什么必须使用Runner.addShutdownHook。如果你想在 jvm 退出时做一些清理,为什么不重载守护进程类的 finalize 方法。使用关闭挂钩而不是finize方法的优势是什么?
还有一个不推荐使用的函数runFinalizersOnExit。如果我将其设置为 false,我相信终结器不会运行。这与 Java 保证结尾器始终在垃圾回收之前运行相矛盾。
无法保证终结器会运行。 在对对象进行垃圾回收时调用。但是,当程序运行时,垃圾回收器可能不会收集任何内容。finalize()
相比之下,关闭钩子在 jvm 正常退出时运行。所以即使这样也不是100%的保证,但它非常接近。只有少数边缘情况下关闭挂钩无法运行。
编辑我查找了未执行关闭钩子的边缘情况
正在执行关闭钩子:
未执行关机挂钩:
关于您的查询
如果你想在 jvm 退出时做一些清理,为什么不重载守护进程类的 finalize 方法呢?
我从这篇文章中找到了很好的信息
finalize()
在垃圾回收器回收对象之前调用。JVM 不保证何时调用此方法。
finalize()
如果对象从 finalize 方法中恢复自身,则 GC 线程只调用一次,而不是 finalize 将不会再次调用。
在您的应用程序中,您可能有一些活动对象,从不调用垃圾回收。
任何由 finalize 方法引发的异常都会被 GC 线程忽略
System.runFinalization(true)
和方法增加了调用方法的概率,但现在这两种方法已被弃用。由于缺乏线程安全性和可能的死锁创建,这些方法非常危险。Runtime.getRuntime().runFinalization(true)
finalize()
回到关闭Hooks,根据oracle文档
public void addShutdownHook(Thread hook) 注册一个新的虚拟机关闭钩子。
Java 虚拟机关闭以响应两种类型的事件:
但即使是甲骨文文档也引用了
关机钩子也应该快速完成工作。当程序调用 exit 时,期望虚拟机将立即关闭并退出。
在极少数情况下,虚拟机可能会中止,即停止运行而不完全关闭
考虑到这两种方法的缺点,您应该遵循以下方法
不要依赖或释放应用程序中的关键资源。finalize()
shutdown hooks
适当地使用块,并在块中释放关键资源。在释放块、捕获和中的资源期间。try{} catch{} finally{}
finally(}
finally{}
Exception
Throwable