JAVA虚拟机关闭钩子(Shutdown Hook)

Java程序经常也会遇到进程挂掉的情况,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码。JAVA中的ShutdownHook提供了比较好的方案。

JDK提供了Java.Runtime.addShutdownHook(Thread hook)方法,可以注册一个JVM关闭的钩子,这个钩子可以在一下几种场景中被调用:

  1. 程序正常退出
  2. 使用System.exit()
  3. 终端使用Ctrl+C触发的中断
  4. 系统关闭
  5. OutOfMemory宕机
  6. 使用Kill pid命令干掉进程(注:在使用kill -9 pid时,是不会被调用的)

下面是JDK1.7中关于钩子的定义:

public void addShutdownHook(Thread hook)

参数:

hook - An initialized but unstarted Thread object

抛出:

IllegalArgumentException - If the specified hook has already been registered, or if it can be determined that the hook is already running or has already been run

IllegalStateException - If the virtual machine is already in the process of shutting down

SecurityException - If a security manager is present and it denies RuntimePermission("shutdownHooks")

从以下版本开始:

1.3

另请参见:

removeShutdownHook(java.lang.Thread), halt(int), exit(int)

首先来测试第一种,程序正常退出的情况:

package com.hook;

import java.util.concurrent.TimeUnit;

public class HookTest
{
	public void start()
	{
		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
			@Override
			public void run()
			{
				System.out.println("Execute Hook.....");
			}
		}));
	}

	public static void main(String[] args)
	{
		new HookTest().start();
		System.out.println("The Application is doing something");

		try
		{
			TimeUnit.MILLISECONDS.sleep(5000);
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
	}
}

运行结果:

The Application is doing something
Execute Hook.....

如上可以看到,当main线程运行结束之后就会调用关闭钩子。

下面再来测试第五种情况(顺序有点乱,表在意这些细节):

package com.hook;

import java.util.concurrent.TimeUnit;

public class HookTest2
{
	public void start()
	{
		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
			@Override
			public void run()
			{
				System.out.println("Execute Hook.....");
			}
		}));
	}

	public static void main(String[] args)
	{
		new HookTest().start();
		System.out.println("The Application is doing something");
		byte[] b = new byte[500*1024*1024];
		try
		{
			TimeUnit.MILLISECONDS.sleep(5000);
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
	}

}

运行参数设置为:-Xmx20M  这样可以保证会有OutOfMemoryError的发生。

运行结果:

The Application is doing something
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at com.hook.HookTest2.main(HookTest2.java:22)
Execute Hook.....

可以看到程序遇到内存溢出错误后调用关闭钩子,与第一种情况中,程序等待5000ms运行结束之后推出调用关闭钩子不同。

接下来再来测试第三种情况:

package com.hook;

import java.util.concurrent.TimeUnit;

public class HookTest3
{
	public void start()
	{
		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
			@Override
			public void run()
			{
				System.out.println("Execute Hook.....");
			}
		}));
	}

	public static void main(String[] args)
	{
		new HookTest3().start();
		Thread thread = new Thread(new Runnable(){

			@Override
			public void run()
			{
				while(true)
				{
					System.out.println("thread is running....");
					try
					{
						TimeUnit.MILLISECONDS.sleep(100);
					}
					catch (InterruptedException e)
					{
						e.printStackTrace();
					}
				}
			}

		});
		thread.start();
	}

}

在命令行中编译:javac com/hook/HookTest3.java

在命令行中运行:java com.hook.HookTest3  (之后按下Ctrl+C)

运行结果:

可以看到效果如预期。

还有几种情况就不一一列出了,有兴趣的读者可以试一下。

时间: 2024-08-05 07:05:38

JAVA虚拟机关闭钩子(Shutdown Hook)的相关文章

java的关闭钩子(Shutdown Hook)

Runtime.getRuntime().addShutdownHook(shutdownHook); 这个方法的含义说明: 这个方法的意思就是在jvm中增加一个关闭的钩子,当jvm关闭的时候,会执行系统中已经设置的所有通过方法addShutdownHook添加的钩子,当系统执行完这些钩子后,jvm才会关闭.所以这些钩子可以在jvm关闭的时候进行内存清理.对象销毁等操作. 用途 1应用程序正常退出,在退出时执行特定的业务逻辑,或者关闭资源等操作.   2虚拟机非正常退出,比如用户按下ctrl+c

Java关闭钩子的应用 - Shutdown Hook

背景 在开发中,遇到这种情况,多个线程同时工作,突然一个线程遇到了fetal的错误,需要立即终止程序,等人工排查解决了问题之后重新启动.但是这样会有一个问题,程序终止时,其他线程可能正在进行重要操作,比如发一个message到另一个模块,并更新数据库状态.突然终止,可能会让这个操作只完成一半,从而导致数据不一致. 解决方案是:参考数据库Transaction原子性的概念,将这一系列重要操作看作一个整体,要么全部完成,要么全部不完成.为方便表述,我们把这一系列重要操作记为操作X. 当程序即将退出时

Tomcat 关闭钩子

使用JAVA的过程中,经常遇到程序启动时初始化一下资源,或生成一下临时文件,程序退出时要清除这些临时文件,或者程序退出时执行一下必要的其他操作.如果程序是通过我们提供的关闭/退出按钮正常退出的,一切还都好处理,但是如果用户直接关闭虚拟机运行的窗口,那一切就会变的比较复杂. 好在java提供了一种优雅的方式去解决这种问题.使得关闭的善后处理的代码能执行.java的关闭钩子能确保总是执行,无论用户如何终止应用程序.除非用户kill,这个是个死穴. 对java而言,虚拟机会对以下几种操作进行关闭: (

Tomcat 学习进阶历程之关闭钩子

使用JAVA的过程中,经常遇到程序启动时初始化一下资源,或生成一下临时文件,程序退出时要清除这些临时文件,或者程序退出时执行一下必要的其他操作.如果程序是通过我们提供的关闭/退出按钮正常退出的,一切还都好处理,但是如果用户直接关闭虚拟机运行的窗口,那一切就会变的比较复杂. 好在java提供了一种优雅的方式去解决这种问题.使得关闭的善后处理的代码能执行.java的关闭钩子能确保总是执行,无论用户如何终止应用程序.除非用户kill,这个是个死穴. 对java而言,虚拟机会对以下几种操作进行关闭: (

JAVA 虚拟机钩子

Shutdown Hook Java程序经常也会遇到进程挂掉的情况,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码.JAVA中的ShutdownHook提供了比较好的方案. JDK提供了Java.Runtime.addShutdownHook(Thread hook)方法,可以注册一个JVM关闭的钩子,这个钩子可以在一下几种场景中被调用: 程序正常退出 使用System.exit() 终端使用Ctrl+C触发的中断 系统关闭 OutOfMemory宕机 使用Ki

Java关闭钩子

Java关闭钩子 在Java程序中可以通过添加关闭钩子,实现在程序退出时关闭资源的功能. 使用Runtime.addShutdownHook(Thread hook)向JVM添加关闭钩子 public void addShutdownHook(Thread hook) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new RuntimePermission("shu

Java关闭钩子的应用

内容:在很多实际的应用环境中,当用户关闭应用程序时,需要做一些善后清理工作.但问题是,用户有时并不会按照推荐的方法关闭程序,很多可能不做清理工作.关闭钩子是一种解决方案,确保无论用户如果关闭应用程序,清理代码总能够得到执行.我们通过向Runtime类注册关闭钩子:是一个已初始化但尚未启动的线程.虚拟机开始启用其关闭序列时,它会以某种未指定的顺序启动所有已注册的关闭钩子,并让它们同时运行. public class ShutdownHookDemo { public void start() {

tomat(16)关闭钩子

[0]REAMDE 0)本文部分文字描述转自:"how tomcat works",旨在学习"tomat(16)关闭钩子"的相关知识: 1)problem+solution: 1.1)problem:在很多实际环境中,当用户关闭应用程序时,并不会按照推荐的方法关闭应用程序,很有可能不做清理工作: 1.2)solution:java 为程序员提供了一种优雅的方法可以在在关闭过程中执行一些代码,以确保那些负责善后处理的代码可能能够执行: 2)在java中,虚拟机会对两类

关闭钩子

在很多实际应用环境中,当用户关了应用程序时,需要做一些善后清理工作,但问题是,用户有时并不会按照推荐的方法关闭应用程序,很有可能不做清理工作,例如在Tomcat的部署应用中,通过实例化一个Server对象来启动servlet容器,并调用其start方法,然后逐个调用组件的start方法,正常情况下,为了让Server对象能够关闭这些已经启动的组件,你应该向指定的端口发送关闭命令,如果你只是简单的突然退出,例如在应用程序过程中关闭控制台,可能会发生一些意想不到的事情. 幸运的是,java为程序员提