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

import java.io.IOException;
import java.util.concurrent.TimeUnit;public class HookTest {public static void main(String[] args) throws IOException {Runtime.getRuntime().addShutdownHook(new Thread(){@Overridepublic void run() {try {System.out.println("这个钩子启动");TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("这个钩子退出");}});}
}

给这段程序注入了一个hook线程,当main结束时,jvm即将退出的时候,hook线程就会被运行

运行这段main函数,可以打印出两条语句:

这个钩子启动

这个钩子退出

一段程序可以注入多个钩子!

那么,hook线程有什么用作呢?

在开发的时候,为了防止某段程序被重复启动,在进程启动的时候会创建一个lock文件,当程序结束或者收到中断信号的时候,就会触发hook从而删除lock文件,在mysql,zookeeper等系统中都可以看到lock文件的存在,下面是一段示例代码:

package Hook;import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Set;
import java.util.concurrent.TimeUnit;public class HookTest {private final static String LOCK_PATH = "/locks";private final static String LOCK_FILE = ".lock";private final static String  PERMISSIONS = "rw--------";public static void main(String[] args) throws IOException {Runtime.getRuntime().addShutdownHook(new Thread(()->{//程序结束时删除.lock文件getLockFile().toFile().delete();}));//检查是否存在lock文件checkRunning();for (;;){try {TimeUnit.MILLISECONDS.sleep(1);System.out.println("程序正在运行");} catch (InterruptedException e) {e.printStackTrace();}}}private static void checkRunning() throws IOException {Path path = getLockFile();if (path.toFile().exists()){throw new RuntimeException("程序正在运行!");}Set<PosixFilePermission> param = PosixFilePermissions.fromString(PERMISSIONS);Files.createFile(path,PosixFilePermissions.asFileAttribute(param));}//获取文件地址private static Path getLockFile() {return Paths.get(LOCK_PATH,LOCK_FILE);}
}

运行这段程序会发生文件夹里面生成了.lock文件

当使用kill pid命令后,jvm会收到中断信号,运行hook线程,删除.lock文件。

注意

  • 应用原因

java程序有时会出现挂掉的情况,有时需要在jvm关掉前执行一些资源释放等的问题。通过java中的Runtime提供的钩子函数shutdownHook提供了比较好的解决方案。

  • 具体场景
  1. 程序正常退出
  2. 使用System.exit()
  3. 终端使用Ctrl+C触发的中断
  4. 系统关闭
  5. OutOfMemory宕机
  6. 使用Kill pid命令干掉进程(注:在使用kill -9 pid时,是不会被调用的)
  • hook线程需要收到中断信号才能开启,如果没有收到中断信号,就不会执行hook,导致.lock不能删除,比如kill -9命令,所以防止程序重复运行,还需要其他手段。
  • hook线程也可以做一些资源释放的操作,类似于try-catch-finally,但不要在hook里面运行复杂的程序,这样会导致程序长时间无法退出。
  • 虚拟机退出:JVM会在所有非后台线程关闭后才会退出,如在一个main线程里新产生一个线程,而该线程阻塞了,那么虚拟机不会退出。后台线程会在所有非后台线程退出后都停止任务。
  • 系统调用System.exit(0):在线程中调用会导致整个系统退出。在调用该代码之后定义代码均不会运行。
  • JAVA的钩子函数是在jvm正常退出时会调用:
    例如在线程上调用System.exit(0)时会调用注册的钩子函数。钩子函数定义:Runtime.getRuntime().addShutdownHook(“定义的线程”);
    ps: linux上kill服务进程会调用钩子函数。

JAVA-JVM的钩子函数相关推荐

  1. 使用JVM钩子函数关闭资源

    一.问题引入 背景 在编写一个需要持续在后台运行的程序的时候遇到了这样的场景:我的程序在主函数中创建了一个线程池周期性地执行任务,我希望主线程和线程池都持续运行,但如果收到外部的关闭信号时,主线程和线 ...

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

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

  3. java 线程钩子_高级并发编程系列六(线程池钩子函数)

    1.考考你 国庆假期快要结束了,准备回到工作岗位的你,是不是已经开始撸起袖子敲代码,反正发完文章我就要准备去加班了,程序员就这样,有干劲对吧 那么来吧,让我们一起分享完高级并发编程系列中,线程池小节的 ...

  4. Java中的JVM关闭钩子

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

  5. java中钩子函数回调函数_钩子函数 和回调函数

    标签: http://blog.csdn.net/lipeionline/article/details/6369657  转自 也可以这样,更容易理解:回调函数就好像是一个中断处理函数,系统在符合你 ...

  6. java中钩子函数回调函数_钩子函数和回调函数

    一般认为,钩子函数就是回调函数的一种,其实还是有差异的,差异地方就是:触发的时机不同. 先说钩子函数: 钩子(Hook)概念源于Windows的消息处理机制,通过设置钩子,应用程序对所有消息事件进行拦 ...

  7. 【转载】Java JVM 运行机制及基本原理

    原博地址:https://zhuanlan.zhihu.com/p/25713880 JVM的基础概念 JVM的中文名称叫Java虚拟机,它是由软件技术模拟出计算机运行的一个虚拟的计算机. JVM也充 ...

  8. 【Python】Flask框架系列(三):session和cookie操作、get/post请求、钩子函数

    在Flask中操作session 示例:设置session的过期时间 完整版 旧版 设置session的过期时间 示例 # encoding: utf-8from flask import Flask ...

  9. Java JVM、JNI、Native Function Interface、Create New Process Native Function API Analysis

    目录 1. JAVA JVM 2. Java JNI: Java Native Interface 3. Java Create New Process Native Function API Ana ...

最新文章

  1. matlab画多个垂直的线段,新手求助,图形最后多出一条垂直线
  2. ICCV 华人团队提出会创作的Paint Transformer,网友反驳:这也要用神经网络?
  3. 以太坊搭建,不能使用puppeth 创建初始块,报错Fatal: Failed to write genesis block: unsupported fork ordering: eip15
  4. 调用函数,计算分段函数的值
  5. response.getWriter()和jsp中out对象的区别
  6. c语言中赋予从2开始的偶数,2013年计算机二级C语言上机试题三十二及答案
  7. python清空列表_Python之列表
  8. 黑色自适应简约个人主页引导页HTML源码
  9. tcs标准编写软件_标准编写工具TCS2017使用指南.PDF
  10. hibernate二级缓存(二)二级缓存实现原理简单剖析
  11. Win10如何ping端口是否开放
  12. 盘古搜索--实例解析
  13. 多益网络社招iq_多益网络2018秋招iq测试题(二)
  14. SAP PO中如何打印预览,找到Message type以及找到驱动程序和Form输出程序
  15. 称“开启千元机快充时代” 魅蓝5s将于15日发布
  16. Houdini图文笔记:VEX知识点小结(一)
  17. 生成word的两种方法 freemaker和POI
  18. h.264 sei信息
  19. mysql数据库(mariadb)
  20. 如何应对运营商插入的广告、被运营商劫持怎么办

热门文章

  1. 2022新版前端开发工具vscode使用教程之下载安装详解
  2. Axure RP8概要页面不见了
  3. CB2401与RFX2401C的兼容区别对比
  4. [BZOJ 2460] 元素
  5. JavaScript - Echarts经典教程-李游Leo-专题视频课程
  6. VS 出现错误“MSB3644 找不到 .NETFramework,Version=v4.6.X 的引用程序集。”的解决方案
  7. 如何判断一家装饰公司怎么样
  8. UE4.26材质剖析-Details-Material
  9. 哪个牌子蓝牙耳机通话质量好?通话质量比较好的蓝牙耳机推荐
  10. 基金从业考试难吗?0316