Java中的JVM关闭钩子

Java中的JVM关闭钩子允许在JVM关闭时执行清理代码,常用于处理系统退出或资源问题。然而,关机钩子不保证执行,可能因内部错误、强杀信号或资源限制而中断。多个钩子执行顺序不确定,且在关闭序列启动后无法注册或删除。此外,钩子应快速完成,避免长计算和用户I/O操作,且需要适当权限。了解这些陷阱有助于正确使用关机钩子。
摘要由CSDN通过智能技术生成

java面试题网站:www.javaoffers.com

Java中的JVM关闭钩子

(翻译篇)关机钩子 也叫 关闭钩子

关机钩子是一种特殊的构造,允许开发人员插入一段代码,以便在JVM关闭时执行。当我们需要在VM关闭时执行特殊的清理操作时,这就很方便了。

通常使用关机钩子处理的一般结构,如确保我们调用特殊过程在应用程序退出(调用system . exit(0))将不工作情况下VM关闭是由于外部原因(例如杀死请求从O / S),或由于资源问题(内存)。我们很快就会看到,shutdown钩子很容易解决这个问题,因为它允许我们提供一个任意的代码块,JVM在关闭时将调用这个代码块。

从表面上看,使用关机钩子是非常直接的。我们所要做的只是编写一个扩展java.lang的类。线程类,并在公共void run()方法中提供我们希望在关闭VM时执行的逻辑。然后,通过调用Runtime.getRuntime(). addshutdownhook (Thread)方法,将这个类的一个实例注册为VM的关机钩子。如果需要删除以前注册的关机钩子,运行时类也提供了removeShutdownHook(Thread)方法。

举例:

public class ShutDownHook 
{ 
  public static void main(String[] args) 
  { 
  
    Runtime.getRuntime().addShutdownHook(new Thread() 
    { 
      public void run() 
      { 
        System.out.println("Shutdown Hook is running !"); 
      } 
    }); 
    System.out.println("Application Terminating ..."); 
  } 
} 

当我们运行上面的代码时,您将看到JVM在完成main方法的执行时调用了shutdown钩子。

输出:

Application Terminating ...
Shutdown Hook is running !

案例2

class ThreadChild extends Thread { 
      
    public void run() { 
          
        System.out.println("In clean up code"); 
        System.out.println("In shutdown hook"); 
    } 
} 
  
class Demo { 
      
    public static void main(String[] args) { 
          
        Runtime current = Runtime.getRuntime(); 
        current.addShutdownHook(new ThreadChild()); 
  
        for(int i = 1; i <= 10; i++)  
            System.out.println("2 X " + i + " = " + 2 * i); 
    } 
} 

输出

2 X 1 = 2
2 X 2 = 4
2 X 3 = 6
2 X 4 = 8
2 X 5 = 10
2 X 6 = 12
2 X 7 = 14
2 X 8 = 16
2 X 9 = 18
2 X 10 = 20
In clean up code
In shutdown hook

就是这么简单

虽然编写关机钩子非常简单,但要正确地使用关机钩子,就需要了解关机钩子背后的内部原理。因此,在本文中,我们将探索关机钩子设计背后的一些陷阱。

  1. 关机钩子在某些情况下可能不会被执行
    首先要记住的是,不能保证shutdown钩子总是运行。如果JVM由于一些内部错误而崩溃,那么它可能在没有机会执行单个指令的情况下崩溃。同样,如果O/S给出一个SIGKILL (http://en.wikipedia.org/wiki/SIGKILL)信号(在Unix/Linux中kill -9)或TerminateProcess (Windows),那么应用程序就需要立即终止,甚至不需要等待任何清理活动。除了上述方法之外,还可以通过调用Runtime.halt()方法终止JVM,而不允许关机钩子运行。
    当应用程序正常终止时(当所有线程结束时,或者当System.exit(0)被调用时),会调用Shutdown钩子。另外,当JVM由于外部原因关闭时,比如用户请求终止(Ctrl+C)、O/S发出的SIGTERM(正常的kill命令,不带-9),或者当操作系统关闭时。

  2. 一旦启动,关机钩子可以在完成前强制停止。
    这实际上是前面解释的情况的一个特例。虽然钩子开始执行,但在操作系统关闭等情况下,它可能在完成之前被终止。在这种情况下,一旦给出了SIGTERM, O/S将等待进程在指定的时间内终止。如果进程没有在这个时间限制内终止,那么O/S通过发出一个SIGTERM(或Windows中的对应项)强制终止进程。因此,当关机钩子执行到一半的时候,很可能会发生这种情况。
    因此,建议确保小心地编写关闭钩子,确保它们快速完成,并且不会导致死锁等情况。另外,JavaDoc[1]特别提到不应该在关机钩子中执行长计算或等待用户I/O操作。

  3. 我们可以有多个关机钩子,但是它们的执行顺序不能保证。
    正如您可能已经正确猜到的addShutdownHook方法的名称(而不是setShutdownHook),您可以注册多个关机钩子。但是JVM并不保证这些多个钩子的执行顺序。JVM可以以任意顺序执行关机挂钩。而且,JVM可能并发地执行所有这些挂钩。.

  4. 我们无法在关机钩子中注册/取消注册关机钩子
    一旦JVM启动了关闭序列,就不允许添加或删除任何现有的关闭钩子。如果尝试这样做,JVM将抛出IllegalStateException。

  5. 一旦启动了关闭序列,就只能通过Runtime.halt()来停止它。
    一旦启动了关闭序列,只有Runtime.halt()(强制终止JVM)可以停止关闭序列的执行(除了SIGKILL等外部影响)。这意味着在关机钩子中调用System.exit()将不起作用。实际上,如果在关机钩子中调用System.exit(), VM可能会被卡住,我们可能不得不强制终止进程。

  6. 使用关机钩子需要安全权限。
    如果我们使用Java安全管理器,那么执行添加/删除关闭钩子的代码需要在运行时拥有关闭钩子权限。如果我们在安全环境中未经允许调用此方法,则会导致SecurityException。

引用:

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Runtime.html addShutdownHook (java.lang.Thread)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值