「java退出钩子」Java 钩子
本篇文章给大家谈谈java退出钩子,以及Java 钩子对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、java多线程时程序运行完成为什么不会自动关闭退出
- 2、JVM对于signal的处理及案例分析
- 3、java进程管理的问题。能不能设置一个JAVA的进程运行一段时间后强行退出,释放内存?
- 4、安装钩子的程序退出前未卸载钩子,那么程序退出后,这个钩子是不是还留在系统中?还起着作用?
java多线程时程序运行完成为什么不会自动关闭退出
具体演示如下:
[java] view plain copy
package test;
public class TestShutDownHook {
public TestShutDownHook() {
doShutDownWork();
}
private void doShutDownWork() {
Runtime run=Runtime.getRuntime();//当前 Java 应用程序相关的运行时对象。
run.addShutdownHook(new Thread(){ //注册新的虚拟机来关闭钩子
@Override
public void run() {
//程序结束时进行的操作
System.out.println("程序结束调用");
}
});
}
public static void main(String[] args) {
new TestShutDownHook();
for (int i = 0; i 1000; i++) { // 在这里增添您需要处理代码 }
System.out.println(i);
}
}
}
在上述程序中,我们可以看到通过在程序中增加Runtime.getRuntime().addShutdownHook(new Thread()) 事件监听,捕获系统退出消息到来,然后,执行我们所需要完成工作,从而使我们的程序更健壮!
望采纳,谢谢。
JVM对于signal的处理及案例分析
Windows的Signal相对少一些, 如下:
Linux的Signal比较多, 如下:
Linux中的Signal可以由 kill 命令发起, 比如 kill -1 [pid] 是对某一个进程发出SIGHUP信息.
JVM 所使用的信号:
信号的类型为 异常、错误、中断和控制 。
表 1
注:
信号名称后提供的数字是该信号的标准数值。
使用 -Xrs(减少信号使用)选项来防止 JVM 处理大多数的信号。有关更多信息,请参阅 Oracle 的 Java™ 应用程序启动程序页面 。
JVM 线程上的信号 1(SIGHUP)、2(SIGINT)、4(SIGILL)、7(SIGBUS)、8(SIGFPE)、11(SIGSEGV)和 15(SIGTERM)导致 JVM 关闭;因此,应用程序信号处理程序不应该尝试从这些信号恢复,除非它不再需要 JVM。
以上表格引用原文链接:
至于JVM是如何处理这些Signal的, 请参考以下链接:
除了JVM默认处理Signal的行为, 我们还可以自定义 SignalHandler 来做一些额外的工作, 比如在关闭JVM之前做一些回收或记录的事情.
例子:
关闭钩子使用的方法也很简单, Runtime.getRuntime().addShutdownHook(Thread hook) 即可。关闭钩子其实可以看成是一个已经初始化了的但还没启动的线程,当 JVM关闭时会并发地执行注册的所有关闭钩子 。
JVM的关闭方式可以分为三种:
注意: Hook线程在JVM 正常关闭 才会执行,在强制关闭时不会执行。(异常关闭没试过, 有空试一下..)
另外在使用关闭钩子还要注意以下几点:
Spring 在初始化容器的时候就会注册一个hook线程用于清理容器.
[图片上传失败...(image-3b9611-1513089974690)]
JVM进程已经不在了, 重启后, 几分钟到半小时之间, 会看到获取不到spring bean的错误日志, 同时系统服务异常.
[图片上传失败...(image-cfc2ef-1513089974690)]
奇怪的是, 2台集群中的其他一台一直都是稳定运行, 只有这台是一直异常状态.
从以上的日志, 可以看出spring容器已经在销毁中了, 感觉是一个正常的关闭系统的流程.
在监控系统(Marvin)中观察了内存的情况, 没有什么波动, 基本排除了oom的情况.
接下来, 我使用jstack输出了当时的线程栈信息, 保留现场痕迹.
[图片上传失败...(image-508b17-1513089974690)]
由上图所示, 从jstack日志中发现了2个关键的点:
自此, 大家可能已经看出来, SIGHUP 正是JVM会处理的Signal之一, 并且在上面的表格中已经清楚的写着 SIGHUP 的操作是 挂起, 让JVM正常退出 , SIGHUP 是 中断 类型的信号, 上面对于 中断 类型的信号是这样描述的: 将从 JVM 进程外部异步发出中断信号以请求关闭。
结论:
可惜的是, 找了很多资料, 始终没有找到确定信号来源的方案. Linux本身也没有相关的日志, JVM也只能获取信号的名称, 对于信号源也是无法确定.(如果有这方面研究的同学望告知..)
找不到根本原因, 那么只能是想办法绕过这个问题.
所幸的是, 在搜索问题的时候, 让我知道了Linux还有一个 nohup 的命令.
nohup命令可以将 程序以忽略挂起信号( SIGHUP)的方式运行起来,被运行的程序的输出信息将不会显示到终端。
于是把JVM的启动脚本改动了一下:
[图片上传失败...(image-7897ca-1513089974690)]
再次启动后, 稳定运行, 问题解决.
实际上通过JVM本身 -Xrs 的参数应该也能控制忽略SIGHUP信号的, 但是时间关系, 我没去实验..
这里案例也让我学到了很多JVM的处理细节.
同时也有了一些思考:
排查线上故障的基本步骤无非就是
实际上, 前面3步基本上已经能解决大部分的问题了, 剩下的一些疑难问题才会用到第4步. 但是第4步的操作对于实时性的要求是最高的, 必须第一时间搞定, 晚一点可能你就捕捉不到有效的证据了.
在出现故障的情况下, 有时候难免手忙脚乱, 如果有一个可以自动化收集现场证据的脚本, 在出现这种疑难问题的时候将会是一个极大的助力.
java进程管理的问题。能不能设置一个JAVA的进程运行一段时间后强行退出,释放内存?
你的设想很好,但是实现起来有一些问题,主要来源于java的安全模型,java的安全模型是不允许你直接访问其他进程的,也就是Java没有办法写钩子程序。
如果得到你要的效果,是可以的,解决办法如下几种:
1、在进程中都做一个Socket的监听某个端口,同时,扫描所有端口看是否有人给你正确的响应,如果响应正确,代表有一个你的进程在执行,那么你做对应处理就好了
2、做基于Native的方式,用C或C++做钩子
注意,销毁的时候注意调用gc来手动释放
安装钩子的程序退出前未卸载钩子,那么程序退出后,这个钩子是不是还留在系统中?还起着作用?
程序退出了,操作系统自动卸载掉你程序安装的钩子的,这个是仅限于应用层的,对于内核层,你是必须把钩子去掉,否则如果你的驱动被卸载了,就会蓝屏了
关于java退出钩子和Java 钩子的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。