Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 关闭钩子与终结器方法_Java_Multithreading_Finalizer_Shutdown Hook - Fatal编程技术网

Java 关闭钩子与终结器方法

Java 关闭钩子与终结器方法,java,multithreading,finalizer,shutdown-hook,Java,Multithreading,Finalizer,Shutdown Hook,我只是不明白为什么必须使用Runtime.addShutdownHook。如果您想在jvm退出时进行一些清理,为什么不重载守护进程类的finalize方法呢。使用shutdownhook-overfinalize方法的优势是什么 还有一个不推荐使用的函数runFinalizersOnExit。如果我将其设置为false,我相信终结器将不会运行。这与java保证终结器总是在垃圾收集之前运行相矛盾。不能保证终结器会一直运行finalize()。但是当程序运行时,垃圾收集器可能不会收集任何东西 相反,

我只是不明白为什么必须使用Runtime.addShutdownHook。如果您想在jvm退出时进行一些清理,为什么不重载守护进程类的finalize方法呢。使用shutdownhook-overfinalize方法的优势是什么


还有一个不推荐使用的函数runFinalizersOnExit。如果我将其设置为false,我相信终结器将不会运行。这与java保证终结器总是在垃圾收集之前运行相矛盾。

不能保证终结器会一直运行<当对象被垃圾收集时,调用code>finalize()。但是当程序运行时,垃圾收集器可能不会收集任何东西

相反,关闭挂钩是在jvm正常退出时运行的。因此,即使这也不是100%的保证,但它非常接近。只有少数情况下关闭挂钩不会运行

编辑 我查找了没有执行关闭挂钩的边缘案例

关闭钩子被执行:

  • 当所有JVM线程都已完成执行时
  • 由于对System.exit()的调用
  • 因为用户点击了CNTRL-C
  • 系统级关闭或用户注销
关闭挂钩未执行:

  • 如果VM由于本机代码中的错误而崩溃,则无法保证钩子是否会运行
  • 若在Linux上使用-kill命令杀死JVM,或者在windows上终止进程,那个么JVM会立即退出
关于您的查询

如果您想在jvm退出时进行一些清理,为什么不重载守护进程类的finalize方法呢

我从中找到了很好的信息

  • 在垃圾收集器回收对象之前调用
    finalize()
    。JVM不保证何时调用此方法

  • 若对象从finalize方法中恢复自身,则GC线程只调用一次
    finalize()
    ,而不会再次调用finalize

  • 在应用程序中,您可能有一些活动对象,这些对象上永远不会调用垃圾收集

  • finalize方法引发的任何异常都被GC线程忽略

  • System.runFinalization(true)
    Runtime.getRuntime().runFinalization(true)
    方法增加了调用
    finalization()
    方法的概率,但现在这两种方法已被弃用。由于缺乏线程安全性和可能的死锁创建,这些方法非常危险

  • 按照甲骨文的说法,回到关机状态

    公共挂钩(螺纹挂钩) 注册新的虚拟机关闭挂钩

    Java虚拟机会关闭以响应两种类型的事件:

  • 当最后一个非守护进程线程退出或调用exit(相当于System.exit)方法时,程序正常退出,或者
  • 虚拟机在响应用户中断(如键入^C)或系统范围事件(如用户注销或系统关闭)时终止
  • 当虚拟机开始其关闭序列时,它将以未指定的顺序启动所有已注册的关闭挂钩,并让它们同时运行。当所有钩子都完成后,如果启用了退出时的终结,那么它将运行所有未调用的终结器
  • 最后,虚拟机将停止。请注意,守护进程线程将在关闭序列期间继续运行,如果通过调用exit方法启动关闭,则非守护进程线程也将继续运行
  • 但即使是oracle文档也引用了这一点

    关机挂钩也应该很快完成工作。当程序调用exit时,预期虚拟机将立即关闭并退出

    在极少数情况下,虚拟机可能会中止,即在未完全关闭的情况下停止运行

    考虑到这两种方法的缺点,您应该遵循以下方法

  • 不要依靠
    finalize()
    shutdown hook
    来释放应用程序中的关键资源

  • 适当地使用
    try{}catch{}finally{}
    块,释放
    finally(}
    块中的关键资源。在释放
    finally{}
    块中的资源时,捕获
    异常
    可丢弃


  • 如果我没记错的话,只有具有守护进程状态的线程,finalize函数肯定不会运行。您能解释一下,为什么finalize可能不会为正常线程运行。还有,在哪些边缘情况下,关闭挂钩在运行期间不会运行shutdown@SKr如果VM正确退出,则在实际线程结束后可能不会对线程对象进行GC例如,离开。@Darkhogg如果您的意思是突然关闭jvm,那么即使是关闭钩子也不会execute@SKr不,我说的是正常关机。最后一个线程结束->VM退出。没有GC。没有终结器。@SKr更新了关机挂钩运行和未运行时的答案“这与java保证终结器总是在垃圾收集之前运行相矛盾。“…Java保证?没有这样的保证。这种方法是在多核处理器不是标准和并发性不太常见的情况下创建的,但现在…它非常不安全,可能会导致不可逆转的系统损坏。任何人都不应该使用
    runFinalizersOnExit