一、问题引入

背景

在编写一个需要持续在后台运行的程序的时候遇到了这样的场景:我的程序在主函数中创建了一个线程池周期性地执行任务,我希望主线程和线程池都持续运行,但如果收到外部的关闭信号时,主线程和线程池也都能同时退出。想到的就是程序结束的时候需要有一个stop()方法去关闭线程池,但是怎么控制这个stop()方法在我想要的时候调用,以什么形式去接收外部的关闭信号也成了需要考虑的问题。

原始思路

最开始的尝试是我将程序的运行和停止分别用"start"和"stop"两种状态表示,然后用一个状态文件state去记录当前的状态(程序启动时默认是"start"),如果想要关闭这个正在运行的程序,就去修改状态文件state,将里面内容变为"stop"。同时在主函数中打开这个状态文件,循环监听里面的内容,如果发现变为"stop",就去调用stop()方法执行关闭逻辑。按照这个思路,我写了一个简单的程序在IDEA中测试了一下效果,发现是可行的。但是当我将程序打包,在mac系统上运行jar包进行测试的时候,不知什么原因,程序总是读到state文件刚打开时的内容,不能检测到state文件的变化,无法按我设想的方式进行关闭。因此只能另想办法。

无意间看见JVM钩子函数的介绍,发现这可能正是我想要的,于是赶紧拿来试一试。

二、JVM钩子使用场景

JVM关闭的情况如下图所示分为三类,第一种是正常的关闭,第二种是异常关闭的情况,第三种是强制关闭的情况。

JVM钩子函数对于前两种方式都可以进行优雅的关闭,但是对最后一种强制关闭就不起作用了。

下面我会根据这三种JVM关闭过程进行简单演示。

正常关闭

代码如下:

public class TestJVMHook {public static void main(String[] args) {Runtime.getRuntime().addShutdownHook(new Thread(()->stop()));start();System.out.println("===程序正常结束===");}public static void start() {System.out.println("===调用start()方法===");}public static void stop() {System.out.println("===调用stop()方法===");}
}

运行结果:

===调用start()方法===
===程序正常结束===
===调用stop()方法===

可以看到,在钩子函数中声明了stop()方法,然后程序正常结束后会自动调用钩子函数。

异常关闭

异常关闭分为OOM和RuntimeException两种情况,我用除数为0的运行时异常来演示。

代码如下:

public class TestJVMHook {public static void main(String[] args) {Runtime.getRuntime().addShutdownHook(new Thread(()->stop()));start();int res = 10/0;System.out.println("===程序结束===");}public static void start() {System.out.println("===调用start()方法===");}public static void stop() {System.out.println("===调用stop()方法===");}
}

运行结果:

===调用start()方法===
===调用stop()方法===
Exception in thread "main" java.lang.ArithmeticException: / by zeroat com.example.TestJVMHook.main(TestJVMHook.java:9)

可以看到执行"10/0"时发生运行时异常,并不会正常打印下一行语句"=程序结束=",但仍然会自动调用钩子函数中stop()方法。

强制关闭

这里我们启动一个循环程序,然后手动去关闭它。

代码如下:

public class TestJVMHook {public static void main(String[] args) throws InterruptedException {Runtime.getRuntime().addShutdownHook(new Thread(()->stop()));int count = 1;start();while(true){System.out.println("循环计数器"+(count++));Thread.sleep(5*1000);}}public static void start() {System.out.println("===调用start()方法===");}public static void stop() {System.out.println("===调用stop()方法===");}
}

启动后查看进程id,然后通过"kill -9 <pid>"强制关闭:

运行结果:

还是上面那段代码,再次启动,采用"kill <pid>"关闭:

发现通过"kill"正常关闭可以有效调用钩子函数,但是"kill -9"强制关闭则不会调用钩子函数。

三、回归问题

经过一系列测试,验证了JVM钩子函数确实可以实现我想要的资源关闭效果。由于我的程序是一个循环程序,需要手动关闭,因此可以在关闭程序的脚本中通过 kill 的方式进行钩子函数的调用。

使用JVM钩子函数关闭资源相关推荐

  1. java钩子函数(hook)以spring源码为例

    一.什么是钩子函数 请问在Spring中,如果JVM异常终止,Spring是如何保证会释放掉占用的资源,比如说数据库连接等资源呢?钩子函数非常简单,简单到只用摘抄一段Spring代码即可. 二.问题 ...

  2. JAVA-JVM的钩子函数

    当jvm进程退出的时候,或者受到了系统的中断信号,hook线程就会启动,一个线程可以注入多个钩子,这是一个实例: import java.io.IOException; import java.uti ...

  3. 一起学并发编程 - 钩子函数(shutdownHook)

    shutdownHook是一种特殊的结构,它允许开发人员插入JVM关闭时执行的一段代码.这种情况在我们需要做特殊清理操作的情况下很有用 <!-- more --> 用途 在Jboss,Je ...

  4. 解读鸿蒙轻内核的监控器:异常钩子函数

    摘要:本篇先介绍下支持的异常钩子函数的类型,异常钩子函数的注册.执行等内部操作API接口,并介绍下使用异常钩子函数的操作接口. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列十七(1) 异常钩 ...

  5. Vue的过滤器,生命周期的钩子函数和使用Vue-router

    一.过滤器 1.局部过滤器 在当前组件内部使用过滤器 给某些数据 添油加醋 //声明 filters:{'过滤器的名字':function(val,a,b){//a 就是alax ,val就是当前的数 ...

  6. k8s pod生命周期、初始化容器、钩子函数、容器探测、重启策略

    pod结构 Pause容器 Pause容器是每个Pod都会有的一个根容器,它的作用有两个 可以以它为根据,评估整个pod的健康状态 可以在根容器上设置IP地址,其他容器都以此IP(Pod IP),以实 ...

  7. 哈哈,咱们团队早就不用try-catch-finally关闭资源了!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 代码一定得写的优雅一点! 你还在使用try-catch-final ...

  8. 你还在使用 try-catch-finally 关闭资源?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:何甜甜在吗 链接:https://juejin.im/pos ...

  9. 使用钩子函数[4] - 钩子链和 CallNextHookEx 的返回值

    SetWindowsHookEx 函数的第一个参数表示钩子类型, 共有 14 种选择, 前面我们已经用过两种: WH_KEYBOARD.WH_MOUSE. 系统会为每一种类型的钩子建立一个表(那就是 ...

最新文章

  1. 【OpenCV】图像的通道分离
  2. 如何读取resources目录下的文件路径(九种方式)
  3. 【深度学习】在PyTorch中使用 LSTM 自动编码器进行时间序列异常检测
  4. ie6 select出现在浮动层上面的解决方法
  5. 周正宁:未来五年属于WebRTC+AV1
  6. java 解决汉诺塔问题
  7. sql 触发器_一键生成某个sql的html--记录执行计划、统计信息、触发器等
  8. 企业发卡修复版源码(短链二维码)
  9. 奈奎斯特定理和香农定理之科普篇
  10. 动软分享社区系统 v1.6 震撼发布!
  11. 用户自定义控件(UserControl)用法大全
  12. 大学计算机基础通俗易懂教材,大学计算机基础(21世纪高等学校计算机规划教材)...
  13. 内窥镜去反光的论文整理(转)
  14. Linux中断子系统(一)中断控制器GIC架构
  15. 中国大学MOOC课程《程序设计入门——C语言》 第8周编程练习
  16. Spatial AI
  17. H5 vue单页面 活体检测
  18. 自媒体推广应该怎么入手,如何去做
  19. linux系统读写eth网卡PHY寄存器工具mdio_cmd
  20. 楼宇自动化专用BACnet网关BL103

热门文章

  1. 追求代码质量: 不要被覆盖报告所迷惑
  2. python opencv 直方图均衡化_Python opencv—直方图/直方图均衡化/直方图比较,pythonopencv...
  3. html出现滚动条页面闪动,CSS3 calc实现滚动条出现页面不跳动闪动
  4. rbf神经网络原理_【新书推荐】【2012.12】智能优化算法原理与应用(李士勇)...
  5. kafka python client:PyKafka vs kafka-python
  6. Oracle 判断CLOB字段是否为null
  7. tuxedo linux 安装
  8. Linux 环境 简单启动 Java程序
  9. aspose-cell 使用
  10. 命令行运行postman