简介

触发的时机有:

当所有的非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挂掉的信息呢?

java 使用的钩子_Java 钩子程序相关推荐

  1. java 1000个线程_java,一个程序建立1000个线程,每一个线程加1到一个变量sum。

    1.程序建立1000个线程,有可能造成系统创建大量线程而导致消耗完系统内存,还会增加创建和销毁线程上所花的时间以及系统资源的开销 2.在创建线程数多的情况下,可以考虑使用线程池 以下是Java自带的几 ...

  2. java怎么加定时器_JAVA WEB程序中添加定时器

    JAVA WEB程序中添加定时器 //这是我的定时器类,用来定时执行某段任务: package com.my.time; import java.text.ParseException; import ...

  3. java端到端_Java应用程序性能监控:复杂分布式应用程序的端到端性能

    java端到端 通过从您的应用程序学习企业APM产品,发现更快,更有效的性能监控. 参加AppDynamics APM导览! 在最复杂和分布式环境中端到端监视Java应用程序性能-专注于业务事务. 自 ...

  4. java在实际应用_Java应用程序如何部署在“现实世界”中?

    这取决于应用程序.有很多选项取决于用户如何使用您的应用程序.通常它被包装成罐子或专门的罐子(战争,耳朵). 理论上,您可以使用.class文件压缩原始目录结构,并提供为用户运行java命令的shell ...

  5. java数字计算结果_Java编写程序之输入一个数字实现该数字阶乘的计算

    需求说明: 编写Java程序,输入一个数字,实现该数字阶乘的计算.一个数字的阶乘是所有小于及等于该数的正整数的积,自然数n的阶乘写作n! .例如,5的阶乘等于1*2*3*4*5,表示为5! = 120 ...

  6. java css js 合并_java Web程序使用wro4j合并、压缩js、css等静态资源

    在Web项目中,js.css合并压缩,不仅有利于减少Http请求数量.减少宽带资源占用,还能有效的管理各种js.css的引入,使整个项目更加有序.而对于访问用户来说,其更大的好处是增加了页面的打开速度 ...

  7. java开发电脑软件_JAVA开发程序员,开发使用笔记本推荐?

    同 java 路过. 买笔记本,我们可以从以下几点来选购参考. "硬参数"CPU 内存 硬盘 显卡 "软参数"屏幕 重量 散热 那依次来按照顺序来介绍下. &q ...

  8. java 进程不关闭_java运行程序关不了窗口

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 package office菜单; import java.awt.Frame; import java.awt.Menu; //菜单组件 import ...

  9. java猴子分桃_java编写程序五只猴子分海滩上的一堆桃子答案

    下面给大家分享的编程题是和猴子分桃有关的内容,那么这道题目是怎样的呢?这道题目又应该如何来做解答?一起来看看具体的题目内容和答案吧. 首先我们要来看一下问题,下面是具体的题目. 一.题目 现在,在海滩 ...

  10. Java中的JVM关闭钩子

    java面试题网站:www.javaoffers.com Java中的JVM关闭钩子 (翻译篇)关机钩子 也叫 关闭钩子 关机钩子是一种特殊的构造,允许开发人员插入一段代码,以便在JVM关闭时执行.当 ...

最新文章

  1. 使用Sentinel配置Redis 3.x主从高可用服务
  2. asp实现批量录入数据
  3. [Swift]LeetCode673. 最长递增子序列的个数 | Number of Longest Increasing Subsequence
  4. Spark On K8S与Spark On YARN方案相比之劣势
  5. 编程基本功:有了范例代码,怎么办?
  6. TensorFlow下安装matplotlib模块
  7. 美团配送事业部尹兵兵加入货拉拉任运力副总裁
  8. 标自然段的序号格式_你可能还不会基本的公文格式
  9. (六)Oracle学习笔记—— 约束
  10. 活性边表算法c语言,《计算机图形学》有序边表填充算法.doc
  11. SpringMVC中解决POST和GET请求中文乱码问题
  12. 学习笔记-状态方程精确离散化
  13. YY直播产品体验报告
  14. python plot 渐变颜色_创建渐变颜色贴图matplotlib
  15. 用c语言编程点菜系统,基于C语言实现点菜系统.pdf
  16. wordpress 背景_如何在WordPress中添加全屏背景图片
  17. win10删除提示找不到该项目
  18. 【论文分享】小样本图片分类方法:AwGCN:Few-Shot Learning With Attention-Weighted Graph Convolutional Networks
  19. 为什么要认证抖音蓝V?怎样申请抖音蓝V认证?
  20. 宝塔同时安装苹果cms海洋cms_苹果cms用宝塔定时采集+添加百度推送教程

热门文章

  1. 伺服电机选型时,惯量匹配和惯量比的问题
  2. 全球高精度5米 12.5米 30米地形(DEM)高程数据(tif格式)下载
  3. 海康威视 java B/S 开发 流程
  4. 应用案例 | 2018款奥迪 A4 Avant 车发动机无法起动故障诊断
  5. c4dr20怎么安装oc渲染器怎么安装_c4d怎么安装oc渲染器/插件
  6. C语言字符与数字的互转
  7. 人工势场法(APF) —— Path Planning
  8. 代码比对方法/代码比对工具
  9. MapGIS10.3Desktop64位学习版带安装教程
  10. 计算机主机运行显示屏黑屏,电脑开机黑屏_电脑启动显示器黑屏的原因和检修-太平洋IT百科...