精华内容
下载资源
问答
  • 简介触发的时机有:当所有的非deamon线程(守护线程)结束, 或者调用了Systrem.exit()方法 而导致的程序正常的退出JVM收到需要关闭自己的信号(比如SIGINT、SIGTERM等,但像SIGKILL,JVM就没有机会去处理了),也或者...

    简介

    触发的时机有:

    当所有的非deamon线程(守护线程)结束, 或者调用了Systrem.exit()方法 而导致的程序正常的退出

    JVM收到需要关闭自己的信号(比如SIGINT、SIGTERM等,但像SIGKILL,JVM就没有机会去处理了),也或者发生如系统关闭这种不可阻挡的事件。

    对于addShutdownHook中的钩子代码,也是有一些要注意的地方,下面列举几点:

    关闭钩子可以注册多个,在关闭JVM时就会起多个线程来运行钩子。通常来说,一个钩子就足够了,但如果需要启用多个钩子,就需要注意并发带来的问题。

    钩子里也要注意对异常的处理,如果不幸抛出了异常,那么钩子的执行序列就会被终止。

    在钩子运行期间,工作线程也在运行,需要考虑到工作线程是否会对钩子的执行带来影响

    钩子里的代码尽可能简洁,否则当像系统关闭等情景可能钩子来不及运行完JVM就被退出了。

    信号触发

    使信号触发JVM的钩子程序

    public class HookTest {

    public static void main(String[] args) {

    Runtime.getRuntime().addShutdownHook(new Hook());

    while(true){}

    }

    static class Hook extends Thread{

    @Override

    public void run() {

    System.out.println("Hook execute!!!");

    }

    }

    }

    运行钩子程序

    nohup java HookTest &

    关闭程序

    kill HookTest_PID

    我们可以在nohup程序中看到Hook execute!!!输出

    我从JVMs and kill signals看到一篇博客, 这个上面总结了哪些信号会导致JVM运行Hook

    signal shutdown runs hook exit code comment

    default (15) yes yes 143 SIGTERM is the default unix kill signal

    0 no - -

    1 (SIGHUP) yes yes 129

    2 (SIGINT) yes yes 130 SIGINT is the signal sent on ^C

    3 (SIGQUIT) no - - 触发 JVM dump threads / stack-traces

    4 (SIGILL) yes no 134 触发 JVM 输出一个 core dump 文件, 同时abort on trap 6

    5 yes no 133 Makes the JVM exit with "Trace/BPT trap: 5"

    6 (SIGABRT) yes no 134 Makes the JVM exit with "Abort trap: 6"

    7 yes no 135 Makes the JVM exit with "EMT trap: 7"

    8 (SIGFPE) yes no 134 Makes the JVM write a core dump and abort on trap 6

    9 (SIGKILL) yes no 137 The JVM is forcibly killed (exits with "Killed: 9")

    10 (SIGBUS) yes no 134 Emulates a "Bus Error"

    11 (SIGSEGV) yes no 134 Emulates a "Segmentation fault"

    12 yes no 140 Makes the JVM exit with "Bad system call: 12"

    13 no - -

    14 yes no 142 Makes the JVM exit with "Alarm clock: 14"

    15 (SIGTERM) yes yes 143 This is the default unix kill signal

    16 no - -

    17 no - 145 Stops the application (sends it to the background), same as ^Z

    18 no - 146 Stops the application (sends it to the background), same as ^Z

    19 no - -

    20 no - -

    21 no - 149 Stops the application (sends it to the background), same as ^Z

    22 no - 150 Stops the application (sends it to the background), same as ^Z

    23 no - -

    24 yes no 152 Makes the JVM exit with "Cputime limit exceeded: 24"

    25 no - -

    26 yes no 154 Makes the JVM exit with "Virtual timer expired: 26"

    27 yes no 155 Makes the JVM exit with "Profiling timer expired: 27"

    28 no - -

    29 no - -

    30 yes no 158 Makes the JVM exit with "User defined signal 1: 30"

    31 yes no 134 Makes the JVM exit on Segmentation fault

    内存溢出触发

    测试JVM栈溢出后调用钩子程序

    public class HookTest {

    public static void main(String[] args) {

    Runtime.getRuntime().addShutdownHook(new Hook());

    exec();

    }

    public static void exec() {

    exec();

    }

    static class Hook extends Thread{

    @Override

    public void run() {

    System.out.println("Hook execute!!!");

    }

    }

    }

    运行后输出为

    D:\testOOM>java HookTest

    Exception in thread "main" java.lang.StackOverflowError

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    ...

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    at HookTest.exec(HookTest.java:9)

    Hook execute!!!

    D:\testOOM>

    为了测试在更加复杂的环境下, Hook的使用情况, 看下面的测试代码

    import java.time.LocalDateTime;

    import java.util.HashMap;

    import java.util.Map;

    import java.util.concurrent.TimeUnit;

    public class HookTest {

    private static Map cache = new HashMap<>();

    public static void main(String[] args) {

    cache.put("abc", "abc");

    Runtime.getRuntime().addShutdownHook(new Hook());

    byte[] bytes = new byte[1024 * 1024 *1024 * 1024];

    }

    static class Hook extends Thread{

    @Override

    public void run() {

    for (int i = 0; i < 100; i++) {

    System.out.println(LocalDateTime.now());

    System.out.println(" freeMemory : " + Runtime.getRuntime().freeMemory());

    System.out.println(" maxMemory : " + Runtime.getRuntime().maxMemory());

    System.out.println(" totalMemory : " + Runtime.getRuntime().totalMemory());

    System.out.println(" currentThread name : " + Thread.currentThread().getName());

    System.out.println(" cache size : " + cache.size());

    cache.put(LocalDateTime.now().toString(), LocalDateTime.now().toString());

    try {

    TimeUnit.SECONDS.sleep(1);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

    }

    }

    运行后的输出结果为

    ζ java HookTest

    2016-07-09T16:12:12.479

    freeMemory : 155922512

    maxMemory : 2375024640

    totalMemory : 160956416

    currentThread name : Thread-0

    cache size : 1

    2016-07-09T16:12:13.480

    freeMemory : 155922512

    maxMemory : 2375024640

    totalMemory : 160956416

    currentThread name : Thread-0

    cache size : 2

    2016-07-09T16:12:14.480

    freeMemory : 155922512

    maxMemory : 2375024640

    totalMemory : 160956416

    currentThread name : Thread-0

    cache size : 3

    2016-07-09T16:12:15.480

    freeMemory : 155922512

    maxMemory : 2375024640

    totalMemory : 160956416

    currentThread name : Thread-0

    cache size : 4

    ...

    正常结束触发

    测试程序正常结束后也会调用钩子程序

    public class HookTest {

    public static void main(String[] args) {

    Runtime.getRuntime().addShutdownHook(new Hook());

    }

    static class Hook extends Thread{

    @Override

    public void run() {

    System.out.println("Hook execute!!!");

    }

    }

    }

    运行结果为

    D:\testOOM>java HookTest

    Hook execute!!!

    D:\testOOM>

    调用exit()触发

    public class HookTest {

    public static void main(String[] args) {

    Runtime.getRuntime().addShutdownHook(new Hook());

    System.exit(0);

    System.out.println("Main over");

    }

    static class Hook extends Thread{

    @Override

    public void run() {

    System.out.println("Hook execute!!!");

    }

    }

    }

    运行结果为

    D:\testOOM>java HookTest

    Hook execute!!!

    D:\testOOM>

    不被触发

    再google上找到了一篇这样的文章Know the JVM Series: Shutdown Hooks里面介绍了钩子程序在什么情况下不会执行

    尽管上面列举出了N多触发钩子程序的示例, 但是并不保证这个钩子程序总是能被触发执行的, 例如

    JVM内部发生错误, 可能还没有来得及触发钩子程序, JVM就挂掉了(JVM 发生内部错误, 有没有日志呢?)

    还有上面我们给出的那个信号表, 如果操作系统发送出上面的信号的话, 同样的, JVM没有执行钩子程序就退出了

    还有调用Runime.halt()函数也不会执行钩子程序

    还有一种情况是, 当操作系统向进程发送一个SIGTERM信号之后, 如果进程没有在指定的时间之内关闭, 那么操作系统会强制将该进程杀掉, 如此一来钩子程序也不会得到完整的执行(因为钩子程序可能执行到一半就被操作系统杀死了). 因此不管是这篇文章还是JDK API都推荐不要在钩子程序里写复杂的业务逻辑, 避免产生死锁或者产生长时间的IO操作, 尽可能快地让钩子程序执行完毕.

    Will shutdown hooks be run if the VM crashes?

    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.

    哎,, 怎么着才能监控JVM挂掉的信息呢?

    展开全文
  • 需求:想要在程序退出的时候,能够进行一些文件的清理,能够进行一些资源的释放,一些运行时的数据的保存。还有一个需求是在退出的时候,需要将阻塞队列里边的数据,处理完再退出。 说明:springboot项目 ...

     需求:想要在程序退出的时候,能够进行一些文件的清理,能够进行一些资源的释放,一些运行时的数据的保存。还有一个需求是在退出的时候,需要将阻塞队列里边的数据,处理完再退出。 

     

      说明:springboot 项目

                 关闭程序的时候,只能使用 kill  pid 的方式终止程序,不能使用 kill  -9  pid 的方式。因为 kill -9 的方式,会直接退出。这个这里不过多的赘述了。

     

       # # 解决方案

      在 application 启动类里边添加如下的代码,其中application启动类就是我们创建springboot 项目的时候就会有的类。然后需要执行的代码放在先撤线程里边

     

    // 定义关闭线程
    Thread shutdownThread = new Thread() {
        public void run() {
            System.out.println("shutdownThread...");
        }
    };
    Runtime.getRuntime().addShutdownHook(shutdownThread);

     

     ~ ps

      写在最后:其实我最想,在 kill  -9  pid 的时候,也能够触发钩子程序。 但是我目前还做不到,因为系统命令 kill -9  就是直接退出,钩子程序也不会执行了。 我见过的能够平滑退出的有 elasticsearch ,它在使用  kill -9 的时候,仍然能够执行一些内容。

     

     

    展开全文
  • 这次做一个比较有意思的实验,我们知道当一个程序如果抛异常了其程序肯定会挂掉,那有木有可能在程序异常退出时能执行一段咱们自己的代码,比如说...首先新建一个java类:比较简单,就是有一个死循环来模拟程序在...

    这次做一个比较有意思的实验,我们知道当一个程序如果抛异常了其程序肯定会挂掉,那有木有可能在程序异常退出时能执行一段咱们自己的代码,比如说服务器在异常退出时需要做一些额外的资源清理,像这种场景就正好是这里有实验的,下面开始,因为这个实验用shell命令演示会比较方便,所以建议实验是在linux、mac系统下,windows上木有这么方便。

    首先新建一个java类:

    38c0336966bbc5b3fbdaf3dc243dc325.png

    cd30b6ab2347afb163b42319d0574bc7.png

    比较简单,就是有一个死循环来模拟程序在工作,编译运行:

    d39d7dc9780bbf587cde893b5d2f899d.png

    咱们可以将这个程序放到后台去运行,不至于阻塞终端:

    1b8c8f78e83438a3891e9d9ad07fc31c.png

    b63f6f5a4920527ac1c0b6c1777d5343.png

    然后此时的运行结果就都输出到了"nohup.out"这个日志文件了,可以通过如下命令去查看:

    6477e81940d293f9c70e57a29be79b37.png

    c7924bcd2db0118135e0e75c4a5a6689.png

    那如果此时用kill命令将咱们这个程序给杀掉,杀掉之后咱们目前程序是没有任何处理的,如下:

    eeaa438e6e2482dcbe43168886e9d3b1.png

    而如果是程序出现了异常那咱们的程序也就直接挂掉了,咱们来改一下程序:

    8a8df2910769f94295493c2ae2e69289.png

    编译运行:

    2aeafd019829de6e71f2512847b7388a.png

    接下来给程序加入一个钩子,当进程死掉之后可以执行咱们的一段逻辑,具体做法如下:

    c69f75fd6b55bd1f348d30950563071d.png

    编译运行:

    c3ca86fa1caa2e70d7677d4e17a5d3c2.gif

    很显然这次当程序抛异常导致程序挂掉之后就正常执行了咱们预期的程序,这也就是钩子程序的作用,那下面再来试验一下如果用kill命令手动去杀那依然可以执行钩子程序么,先将异常给注释掉:

    2bfd390d0ba7b95e2f771e459e0654f5.png

    再来编译运行:

    11ca9c2d017b3fd36bd1bc7d245178a7.gif

    嗯~~正常被执行了,但是kill -9就不一样了,下面演示一下:

    72001c1a7ba6026126dc65245baa3935.gif

    很显然这次程序就直接挂掉了,因为kill -9属于强杀,对于这种情况咱们的钩子程序是不管用的,所以对于服务器的管理人员杀掉程序时一般是非常忌讳用kill -9的。

    展开全文
  • 以前在开发时只知道依靠数据库事务来保证...这时我们可以依靠java提供的一个工具方法:java.lang.Runtime.addShutdownHook(Thread hook)addShutdownHook方法可以加入一个钩子,在程序退出时触发该钩子。(退出是指ctr...

    以前在开发时只知道依靠数据库事务来保证程序关闭时数据的完整性。

    但有些时候一个业务上要求的原子操作,不一定只包括数据库,比如外部接口或者消息队列。此时数据库事务就无能为力了。

    这时我们可以依靠java提供的一个工具方法:java.lang.Runtime.addShutdownHook(Thread hook)

    addShutdownHook方法可以加入一个钩子,在程序退出时触发该钩子。

    (退出是指ctrl+c或者kill -15,但如果用kill -9 那是没办法的,具体有关kill的signal机制有篇大牛的文章《Linux 信号signal处理机制》)

    钩子做什么操作都可以,甚至可以循环检查某个线程的状态,直到业务线程正常退出,再结束钩子程序就可以保证业务线程的完整性

    例子程序如下:

    实例程序在执行过程中按下ctrl -c或者 kill -15,由于钩子程序的循环检测,能够保证线程执行完毕后,程序才关闭。

    937a03f92563

    1/**2* Created by IntelliJ IDEA.3* User: Luo4* Date: 13-7-115* Time: 下午3:126*/78publicclassTestShutdownHook {910/**11* 测试线程,用于模拟一个原子操作12*/13privatestaticclassTaskThreadextendsThread {14@Override15publicvoidrun() {16System.out.println("thread begin ...");17TestShutdownHook.sleep(1000);18System.out.println("task 1 ok ...");19TestShutdownHook.sleep(1000);20System.out.println("task 2 ok ...");21TestShutdownHook.sleep(1000);22System.out.println("task 3 ok ...");23TestShutdownHook.sleep(1000);24System.out.println("task 4 ok ...");25TestShutdownHook.sleep(1000);26System.out.println("task 5 ok ...");2728System.out.println("thread end\n\n");29}30}3132/**33* 注册hook程序,保证线程能够完整执行34*@paramcheckThread35*/36privatestaticvoidaddShutdownHook(finalThread checkThread) {37//为了保证TaskThread不在中途退出,添加ShutdownHook38Runtime.getRuntime().addShutdownHook(newThread() {39publicvoidrun() {40System.out.println("收到关闭信号,hook起动,开始检测线程状态 ...");41//不断检测一次执行状态,如果线程一直没有执行完毕,超时后,放弃等待      \42for(inti = 0; i < 100; i++) {43if(checkThread.getState() ==State.TERMINATED) {44System.out.println("检测到线程执行完毕,退出hook");45return;46}47TestShutdownHook.sleep(100);48}49System.out.println("检测超时,放弃等待,退出hook,此时线程会被强制关闭");50}51});52}535455privatestaticvoidsleep(longmillis) {56try{57Thread.sleep(millis);58}catch(InterruptedException e) {59e.printStackTrace();60}61}6263publicstaticvoidmain(String[] args)throwsInterruptedException {64finalTaskThread taskThread =newTaskThread();65//为了保证TaskThread不在中途退出,添加ShutdownHook66addShutdownHook(taskThread);67//执行TaskThread68taskThread.start();69}7071}

    937a03f92563

    展开全文
  • java 键盘钩子程序

    2010-11-19 15:52:17
    http://d.download.csdn.net/down/1720478/qwe852012
  • 1.钩子程序执行时机: 当程序正常退出,系统调用 System.exit方法或虚拟机被关闭时才会执行添加的shutdownHook线程。其中shutdownHook是一个已初始化但并不有启动的线程,当jvm关闭的时候,会执行系统中已经设置的...
  • 在线上Java程序中经常遇到进程程挂掉,一些...JDK在1.3之后提供了Java Runtime.addShutdownHook(Thread hook)方法,可以注册一个JVM关闭的钩子,这个钩子可以在以下几种场景被调用:1)程序正常退出2)使用System.exit...
  • java鼠标钩子 运行程序 显示鼠标位置
  • 实例测试二:下面实例程序在执行过程中按下ctrl -c或者 kill -15,由于钩子程序的循环检测,能够保证线程执行完毕后,程序才关闭。 public classTestShutdownHook {/*** 测试线程,用于模拟一个原子操作*/ private ...
  • java的鼠标键盘钩子程序swt实现

    热门讨论 2009-04-24 16:35:26
    java的鼠标键盘钩子程序swt实现,目前能找到的比较方现成的实现,用起来也比较方便。
  • 在线上Java程序中经常遇到进程程挂掉,一些...JDK在1.3之后提供了Java Runtime.addShutdownHook(Thread hook)方法,可以注册一个JVM关闭的钩子,这个钩子可以在以下几种场景被调用:1)程序正常退出2)使用System.exit...
  • 这次做一个比较有意思的实验,我们知道当一个程序如果抛异常了其程序肯定会挂掉,那有木有可能在程序异常退出时能执行一段咱们自己的代码,比如说服务器在异常退出时需要做一些额外的资源清理,像这种场景就正好是...
  • 我在服务器里新新建了个tomcat的docker,开的端口是8080,使用ip:8080访问时可以看到tomcat的欢迎页面然后我在本地使用maven命令行打包到tomcat里上传也已经成功,在manager页面里也能看到我的程序但是我按照ip:8080...
  • 以前在开发时只知道依靠数据库事务来保证程序关闭时数据的完整性。 但有些时候一个业务上要求的原子操作,不一定只包括数据库,比如外部接口或者消息队列...addShutdownHook方法可以加入一个钩子,在程序退出时触发
  • 钩子java_钩子 java

    2021-03-05 18:48:45
    每张票:作为创建自定义关机钩子的一种解决方法,您可以创建一个自定义处理程序并将其安装在根记录器上。LogManager $ Cleaner的第一步是关闭记录器上所有已安装的处理程序。清理程序调用自定义处理程序的关闭后,您...
  • //该方法在程序结束(意外退出,正常退出)时 可以做一些资源释放的工作 //例如 tomcat在shutdown时 你会看到tomcat并没有立即结束 //但是在linux下 使用 kill-9 杀死程序时 该方法不会得到执行 Runtime....
  • java钩子-ShutdownHook

    2015-07-25 21:00:40
    在线上Java程序中经常遇到进程程挂掉,一些状态没有正确的保存下来或者程序中尚有一些未完成的任务,这时候就需要在JVM关掉的时候执行一些清理现场的代码。Java中得ShutdownHook提供了比较好的方案。 JDK在1.3之后...
  • 一、接收信号 1、在Linux中执行kill -l查看信号,共有...二、注册钩子 Runtime.getRuntime().addShutdownHook(new Thread("xx-shutdown-hook") { @Override public void run() { //资源释放动作 } });  
  • 我在jBuilder里面用swing实现的该程序,其实很简单,就是调用了里面库文件的两个监听事件,当程序失去焦点以后仍然可以显示出当前鼠标的坐标。之所以上传是因为不少人可能对swt extension并不熟悉,导致自己用JNI...
  • Java提供注册钩子线程,在JVM进程关闭之前,会自动执行这个钩子线程。 运用这个技巧,可以再JVM关闭之前,释放一些系统资源。 这个功能利用的是Runtime类来实现。 public class Hook { public static ...
  • 测试代码:public class TestHook {public static boolean hookFlag = false;public static void main(String[] args) {Thread shutDownThread = new Thread() {public void run() {TestHook.hookFlag = true;...
  • 这次做一个比较有意思的实验,我们知道当一个程序如果抛异常了其程序肯定会挂掉,那有木有可能在程序异常退出时能执行一段咱们自己的代码,比如说服务器在异常退出时需要做一些额外的资源清理,像这种场景就正好是...
  • Java关闭钩子

    2016-03-16 15:20:00
    Java程序中可以通过添加关闭钩子,实现在程序退出时关闭资源的功能。使用Runtime.addShutdownHook(Thread hook)向JVM添加关闭钩子 public void addShutdownHook(Thread hook) { SecurityManager sm = System...
  • JAVA关闭钩子

    2017-12-20 21:48:00
    JAVA的关闭钩子: 1、 一般应用程序在关闭时都需要做一些善后清理工作,但是用户并不会总是按照推荐的方法关闭应用程序,比如用户直接关闭控制台程序或者按下Ctrl+C结束应用程序,这样就导致清理工作得不到执行,...
  • java web 程序 可不可以在客户端运行键盘钩子 要 怎么做?

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 392
精华内容 156
关键字:

java钩子程序

java 订阅