专栏首页zhishengJAVA虚拟机关闭钩子(Shutdown Hook)

JAVA虚拟机关闭钩子(Shutdown Hook)

前言

当你认真的去看一个组件的源码的时候,你会经常看见这种关闭钩子的函数,如果你不了解的话,谷歌一下,你就会发现如下文章就是搜索引擎出来的第一篇,不愧是出自我们优秀的厮哒哒之笔。

正文

Java 程序经常也会遇到进程挂掉的情况,一些状态没有正确的保存下来,这时候就需要在 JVM 关掉的时候执行一些清理现场的代码。JAVA 中的 ShutdownHook 提供了比较好的方案。

JDK提供了Java.Runtime.addShutdownHook(Thread hook)方法,可以注册一个JVM关闭的钩子,这个钩子可以在一下几种场景中被调用:

1、程序正常退出

2、使用 System.exit()

3、终端使用 Ctrl+C 触发的中断

4、系统关闭

5、OutOfMemory 宕机

6、使用 Kill pid 命令干掉进程(注:在使用 kill -9 pid 时,是不会被调用的)

下面

是JDK1.7中关于钩子的定义:

public void addShutdownHook(Thread hook)

参数: hook - An initialized but unstarted Thread object

抛出:

IllegalArgumentException - If the specified hook has already been registered, or if it can be determined that the hook is already running or has already been run IllegalStateException - If the virtual machine is already in the process of shutting down SecurityException - If a security manager is present and it denies RuntimePermission("shutdownHooks")

从以下版本开始: 1.3

另请参见: removeShutdownHook(java.lang.Thread), halt(int), exit(int)

首先来测试第一种

程序正常退出的情况

 1package com.hook;
 2
 3import java.util.concurrent.TimeUnit;
 4
 5public class HookTest
 6{
 7    public void start()
 8    {
 9        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
10            @Override
11            public void run()
12            {
13                System.out.println("Execute Hook.....");
14            }
15        }));
16    }
17
18    public static void main(String[] args)
19    {
20        new HookTest().start();
21        System.out.println("The Application is doing something");
22
23        try
24        {
25            TimeUnit.MILLISECONDS.sleep(5000);
26        }
27        catch (InterruptedException e)
28        {
29            e.printStackTrace();
30        }
31    }
32}

运行结果:

1The Application is doing something
2Execute Hook.....

如上可以看到,当main线程运行结束之后就会调用关闭钩子。

下面再来测试第五种情况(顺序有点乱,表在意这些细节)

OutOfMemory 宕机

 1package com.hook;
 2
 3import java.util.concurrent.TimeUnit;
 4
 5public class HookTest2
 6{
 7    public void start()
 8    {
 9        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
10            @Override
11            public void run()
12            {
13                System.out.println("Execute Hook.....");
14            }
15        }));
16    }
17
18    public static void main(String[] args)
19    {
20        new HookTest().start();
21        System.out.println("The Application is doing something");
22        byte[] b = new byte[500*1024*1024];
23        try
24        {
25            TimeUnit.MILLISECONDS.sleep(5000);
26        }
27        catch (InterruptedException e)
28        {
29            e.printStackTrace();
30        }
31    }
32
33}

运行参数设置为:-Xmx20M 这样可以保证会有 OutOfMemoryError 的发生。

运行结果:

1The Application is doing something
2Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
3    at com.hook.HookTest2.main(HookTest2.java:22)
4Execute Hook.....

可以看到程序遇到内存溢出错误后调用关闭钩子,与第一种情况中,程序等待 5000ms 运行结束之后推出调用关闭钩子不同。

接下来再来测试第三种情况

终端使用 Ctrl+C 触发的中断

 1package com.hook;
 2
 3import java.util.concurrent.TimeUnit;
 4
 5public class HookTest3
 6{
 7    public void start()
 8    {
 9        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
10            @Override
11            public void run()
12            {
13                System.out.println("Execute Hook.....");
14            }
15        }));
16    }
17
18    public static void main(String[] args)
19    {
20        new HookTest3().start();
21        Thread thread = new Thread(new Runnable(){
22
23            @Override
24            public void run()
25            {
26                while(true)
27                {
28                    System.out.println("thread is running....");
29                    try
30                    {
31                        TimeUnit.MILLISECONDS.sleep(100);
32                    }
33                    catch (InterruptedException e)
34                    {
35                        e.printStackTrace();
36                    }
37                }
38            }
39
40        });
41        thread.start();
42    }
43
44}

在命令行中编译:javac com/hook/HookTest3.java

在命令行中运行:java com.hook.HookTest3 (之后按下Ctrl+C)

运行结果:

可以看到效果如预期。 还有几种情况就不一一列出了,有兴趣的读者可以把剩余的几个也测试一下。

本文分享自微信公众号 - zhisheng(zhisheng_blog)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-09-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 假如我是面试官,我会这样虐你

    4、你为什么要离开上家公司?你上家公司在xxx,我们公司在xxx,离这么远为什么要选择我们这里?

    zhisheng
  • 0Day技术分析-2-栈溢出原理

    栈溢出原理 1 什么是栈 1.1. 缓冲区 我们向一个杯子里倒水,如果我们倒的水超出了杯子的容量,水就会溢出来。 在我们写程序的时候也可能会用到一些临时的变量 ...

    zhisheng
  • 面试官问你MySQL的优化,看这篇文章就够了

    MySQL对于IN做了相应的优化,即将IN中的常量全部存储在一个数组里面,而且这个数组是排好序的。但是如果数值较多,产生的消耗也是比较大的。再例如:select...

    zhisheng
  • android使用LruCache对listview加载图片时候优化处理

    注意:LruCache是有版本限制的,低版本的sdk需要在libs文件夹添加相应的support-4v文件。 本文改造的大部分是参考http://www.i...

    xiangzhihong
  • java应用CAS

      CAS(Compare and Swap),即比较并替换。jdk里的大量源码通过CAS来提供线程安全操作,比如AtomicInteger类。下面我们来分析一...

    良辰美景TT
  • Java 多线程编程(上)

    https://blog.csdn.net/weixin_44510615/article/details/102617286

    润森
  • 封装自己的dapper lambda扩展-设计篇

    昨天开源了业务业余时间自己封装的dapper lambda扩展,同时写了篇博文《编写自己的dapper lambda扩展-使用篇》简单的介绍了下其使用,今天将分...

    陈珙
  • Java外观模式(门面模式Facade)

      外观模式也叫门面模式,是开发过程中使用频率非常高的一种设计模式,但非常容易理解。

    用户4919348
  • 常见设计模式面试必备

    1、单例类只有一个实例对象; 2、该单例对象必须由单例类自行创建; 3、单例类对外提供一个访问该单例的全局访问点;

    挨踢小子部落阁
  • 结合 MultiType 实现加载更多

    MultiType 是一个分发管理类,帮助我们轻松实现复杂布局.建议大家阅读源码,作者的思路并不复杂但很巧妙.

    夏洛克的猫

扫码关注云+社区

领取腾讯云代金券