Runtime.getRuntime().addShutdownHook(Thread thread) 程序关闭时钩子,优雅退出程序
根据 Java API, 所谓 shutdown hook 就是已经初始化但尚未开始执行的线程对象。在Runtime 注册后,如果JVM要停止前,这些 shutdown hook 便开始执行。也就是在你的程序结束前,
执行一些清理工作,尤其是没有用户界面的程序。 这些 shutdown hook 都是些线程对象,因此,你的清理工作要写在 run() 里。根据 Java API,你的清理工作不能太重了,要尽快结束。
但仍然可以对数据库进行操作。问题是这个度该如何把握。
Java 虚拟机会为了响应以下两类事件而关闭:
程序正常退出:这发生在最后的非守护线程退出时,或者在调用 exit(等同于System.exit)方法时。
为响应用户中断而终止虚拟机:如键入 ^C(注:也就是我们再dos窗口下常用的Ctrl+C退出命令);或发生系统事件,比如用户注销或系统关闭。
shutdown hook只是一个已初始化但尚未启动的线程。虚拟机开始启用其关闭序列时,它会以某种未指定的顺序启动所有已注册的关闭挂钩,并让它们同时运行。运行完所有的挂钩后,如果已启用退出终结,那么虚拟机接着会运行所有未调用的终结方法。最后,虚拟机会暂停。注意,关闭序列期间会继续运行守护线程,如果通过调用 exit 方法来发起关闭序列,那么也会继续运行非守护线程。
一旦开始了关闭序列,则只能通过调用 halt 方法来停止这个序列,此方法可强行终止虚拟机。
一旦开始了关闭序列,则不可能注册新的关闭挂钩或取消注册先前已注册的挂钩。尝试执行这些操作会导致抛出 IllegalStateException。
关闭挂钩可在虚拟机生命周期中的特定时间运行,因此应保护性地对其进行编码。特别是应将关闭挂钩编写为线程安全的,并尽可能地避免死锁。关闭挂钩还应该不盲目地依靠某些服务,这些服务可能已注册了自己的关闭挂钩,所以其本身可能正处于关闭进程中。
关闭挂钩应该快速地完成其工作。当程序调用 exit 时,虚拟机应该迅速地关闭并退出。由于用户注销或系统关闭而终止虚拟机时,底层的操作系统可能只允许在固定的时间内关闭并退出。因此在关闭挂钩中尝试进行任何用户交互或执行长时间的计算都是不明智的。
与其他所有线程一样,通过调用线程 ThreadGroup 对象的 uncaughtException 方法,可在关闭挂钩中处理未捕获的异常。此方法的默认实现是将该异常的堆栈跟踪 (stack trace) 打印至 System.err 并终止线程;它不会导致虚拟机退出或暂停。
仅在很少的情况下,虚拟机可能会中止,也就是没有完全关闭就停止运行。虚拟机被外部终止时会出现这种现象,比如在 Unix 上使用 SIGKILL 信号或者在 Microsoft Windows 上调用 TerminateProcess。如果由于内部数据结构损坏或试图访问不存在的内存而导致本机方法执行错误,那么可能也会中止虚拟机。如果虚拟机中止,则无法保证是否将运行关闭挂钩。(比如现在我遇到的 连接数据库,因为是用的项目初始化内存中的数据连接,用这个方法时在window tomcat上运行正常,到linux中weblogic上运行就异常终止)
注:
在eclipse环境下,程序运行时的那个红色小方形按钮是强制终止程序,也就是相当于kill进程。因此这时候,如果你的程序中有一个hook,那么它就不会执行。因为按照上文的说法,只有在两种情况下运行hook中的程序。这一点和tomcat的程序关闭有点类似,tomcat中的listener中的contextDestroyed()方法也是在jvm关闭的时候才执行这个函数里面的程序。而我们如果直接关掉tomcat的运行窗口,就相当于直接kill掉进程了,因此并不会执行这个函数,但是如果使用的是tomcat里面的shutdown.bat命令,那么这个函数就会执行。
所以对于意外关闭JVM或者强制杀死进程的情况,想要清理垃圾或者一些资源回收的问题,本文的addShutdownHook的方法也不管用。
假如你在程序中还开启了一个端口,那么意外的程序终止,这个端口还被占用,并没有被释放,那么下一次程序重启或者别的程序要使用这个端口的时候,就会出现端口被占用的情况。
对于addShutdownHook()中的Hook,这个线程里面更不能出现死循环的情况,因为这样的话,那么当程序正常终止的时候,就会出现程序关闭不了的情况。
原地址:https://blog.csdn.net/wk1134314305/article/details/78504269
Runtime.getRuntime().addShutdownHook(Thread thread) 程序关闭时钩子,优雅退出程序的更多相关文章
- 使用RunTime.getRunTime().addShutdownHook优雅关闭线程池
有时候我们用到的程序不一定总是在JVM里面驻守,可能调用完就不用了,释放资源. RunTime.getRunTime().addShutdownHook的作用就是在JVM销毁前执行的一个线程.当然这个 ...
- 关于jvm钩子 Runtime.getRuntime().addShutdownHook
转自: http://www.cnblogs.com/nexiyi/p/java_add_ShutdownHook.html 在线上Java程序中经常遇到进程程挂掉,一些状态没有正确的保存下来,这时候 ...
- RunTime.getRunTime().addShutdownHook的用法
今天在阅读Tomcat源码的时候,catalina这个类中使用了下边的代码,不是很了解,所以google了一下,然后测试下方法,Tomcat中的相关代码如下: Runtime.getRuntime() ...
- Runtime.getRuntime().addShutdownHook(Thread)
Runtime.getRuntime().addShutdownHook(Thread)为虚拟机添加关闭时添加钩子线程
- indy9在程序关闭时出现terminate thread timeout的BUG解决办法
indy9在程序关闭时出现terminate thread timeout的BUG解决办法 INDY9线程有BUG,在退出程序的时候会报错:terminate thread timeout(终止线程超 ...
- Runtime.getRuntime().addShutdownHook
Runtime.getRuntime().addShutdownHook(shutdownHook); 这个方法的含义说明: 这个方法的意思就是在jvm中增加一个关闭的钩子,当jvm关闭的时候,会 ...
- Runtime.getRuntime().addShutdownHook(shutdownHook);
今天在阅读Tomcat源码的时候,catalina这个类中使用了下边的代码,不是很了解,所以google了一下,然后测试下方法,Tomcat中的相关代码如下: Runtime.getRuntime() ...
- RunTime.getRunTime().addShutdownHook用法
今天在阅读Tomcat源码的时候,catalina这个类中使用了下边的代码,不是很了解,所以google了一下,然后测试下方法,Tomcat中的相关代码如下: Runtime.getRuntime() ...
- Java中RunTime.getRunTime().addShutdownHook用法
今天在阅读Tomcat源码的时候,catalina这个类中使用了下边的代码,不是很了解,所以google了一下,然后测试下方法,Tomcat中的相关代码如下: Runtime.getRuntime() ...
随机推荐
- 关于<asp:checkBoxList>控件的对齐方法
定义和用法 TextAlign 属性用于获取或设置 CheckBoxList 项目的文本的文本对齐方式. 语法 <asp:CheckBoxList TextAlign="align&q ...
- python基础学习17----json&pickle&shelve
json和pickle的功能是对数据进行序列化 将对象转换为可通过网络传输或可以存储到本地磁盘的数据格式(如:XML.JSON或特定格式的字节串)的过程称为序列化:反之,则称为反序列化 json模块 ...
- python下以api形式调用tesseract识别图片验证码
一.背景 之前在博文中介绍在python中如何调用tesseract ocr引擎,当时主要介绍了shell模式,shell模式需要安装tesseract程序,并且效率相对略低. 今天介绍api形式的调 ...
- 利用windows的计划任务和eKing.CmdReadFileAndSendEmailOper(控制台小程序)实现远程登录服务器的邮件告警提醒
一.场景摘要: 1.windows计划任务中,有一个用户登录时候触发的事件 2.cmd命令:netstat -ano | find "3389" 可以看到当前远程登录的IP 3 ...
- MySQL基础之---mysqlimport工具和LOAD DATA命令导入文本文件
1.mysqlimport工具的使用 看一下命令的使用方法: shell > mysqlimport -u root -p [--LOCAL] DBname File [option] --f ...
- Docker容器学习与分享03
Docker容器的基本操作 所有的docker命令都是以docker开头,也就是指调用docker程序.我学习的第一个命令就是docker run,运行一个容器.以Docker分享02中的容器为例: ...
- Mysql学习第二天
Mysql语句执行 用户登录与管理 mysql -uroot -p -hlocalhost test # 指定登录test数据库 mysql -uroot -p -hlocalhost company ...
- apk静态注射[转]-未实践
原文:http://free0coding.iteye.com/blog/1684263 1.将需要注入的代码块打包成jar1,释放一个公共类的静态方法a 2.反编译apk得到smali文件,在适当 ...
- Spirng MVC 重定向传递对象
在 Spring MVC 中我们会经常遇到重定向. @RequestMapping("/order/saveorder.html") public String saveOrder ...
- Cobalt Strike深入使用
System Profiler使用 System Profiler 模块,搜集目标的各类机器信息(操作系统版本,浏览器版本等) Attacks->web drive-by->System ...