Java shutdown hook are handy to run some code when program exit. We can use java.lang.Runtime.addShutdownHook(Thread t) method to add a shutdown hook in the JVM.

程序退出时,使用Java shutdown钩子可以方便地运行一些代码。 我们可以使用java.lang.Runtime.addShutdownHook(Thread t)方法在JVM中添加一个关闭钩子。

(Java shutdown hook)

Java shutdown hook runs in these two cases.

在这两种情况下,将运行Java shutdown挂钩。





  1. The program exits normally, or we call System.exit() method to terminate the program. Read more about Java System Class. 该程序正常退出,或者我们调用System.exit()方法终止该程序。 阅读有关Java System Class的更多信息。
  2. User interrupts such as Ctrl+C, system shutdown etc.

Important points about Java Shutdown Hook are;

有关Java Shutdown Hook的要点是:

  1. We can add multiple shutdown hooks using Runtime addShutdownHook() method. 我们可以使用Runtime addShutdownHook()方法添加多个关闭挂钩。
  2. Shutdown hooks are initialized but not-started threads. They start when JVM shutdown triggers. 关机挂钩是已初始化但未启动的线程 。 它们在JVM关闭触发时启动。
  3. We can’t determine the order in which shutdown hooks will execute, just like multiple threads executions.
  4. All un-invoked finalizers are executed if finalization-on-exit has been enabled. 如果启用了退出时终结,则将执行所有未调用的终结器。
  5. There is no guarantee that shutdown hooks will execute, such as system crash, kill command etc. So you should use it only for critical scenarios such as making sure critical resources are released etc.
  6. You can remove a hook using Runtime.getRuntime().removeShutdownHook(hook) method. 您可以使用Runtime.getRuntime().removeShutdownHook(hook)方法删除钩子。
  7. Once shutdown hooks are started, it’s not possible to remove them. You will get IllegalStateException. 启动关闭挂钩后,将无法删除它们。 您将获得IllegalStateException
  8. You will get SecurityException if security manager is present and it denies RuntimePermission("shutdownHooks"). 如果存在安全管理器并且拒绝RuntimePermission("shutdownHooks")则将获得SecurityException。

(Java shutdown hook example)

So let’s see example of shutdown hook in java. Here is a simple program where I am reading a file line by line from some directory and processing it. I am having program state saved in a static variable so that shutdown hook can access it.

因此,让我们来看一下Java中的shutdown hook的示例。 这是一个简单的程序,其中我从某个目录中逐行读取文件并进行处理。 我将程序状态保存在静态变量中,以便关机挂钩可以访问它。

package com.journaldev.shutdownhook;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;

public class FilesProcessor {

	public static String status = "STOPPED";
	public static String fileName = "";

	public static void main(String[] args) {
		String directory = "/Users/pankaj/temp";
		Runtime.getRuntime().addShutdownHook(new ProcessorHook());
		File dir = new File(directory);

		File[] txtFiles = dir.listFiles(new FilenameFilter() {

			@Override
			public boolean accept(File dir, String name) {
				if (name.endsWith(".txt"))
					return true;
				else
					return false;
			}
		});

		for (File file : txtFiles) {
			System.out.println(file.getName());
			BufferedReader reader = null;
			status = "STARTED";
			fileName = file.getName();
			try {
				FileReader fr = new FileReader(file);
				reader = new BufferedReader(fr);
				String line;

				line = reader.readLine();

				while (line != null) {
					System.out.println(line);
					Thread.sleep(1000); // assuming it takes 1 second to process each record
					// read next line
					line = reader.readLine();
				}
				status = "PROCESSED";
			} catch (IOException | InterruptedException e) {
				status = "ERROR";
				e.printStackTrace();
			}finally{
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		status="FINISHED";
	}

}

Most important part of above code is line no 16 where we are adding the shutdown hook, below is the implementation class.

上面代码中最重要的部分是第16行,我们在其中添加了shutdown钩子,下面是实现类。





package com.journaldev.shutdownhook;

public class ProcessorHook extends Thread {

	@Override
	public void run(){
		System.out.println("Status="+FilesProcessor.status);
		System.out.println("FileName="+FilesProcessor.fileName);
		if(!FilesProcessor.status.equals("FINISHED")){
			System.out.println("Seems some error, sending alert");
		}
		
	}
}

It’s a very simple use, I am just logging state when the shutdown hook started and if it was not finished already, then send an alert (Not actually, its just logging here).

这是一种非常简单的用法,我只是在记录关闭挂钩开始时的状态,如果还没有完成,则发送警报(实际上不是在这里记录它)。





Let’s see some program execution through terminal.

让我们看看通过终端执行一些程序。

  1. Program terminated using Ctrl+C command.As you can see in the above image, shutdown hook started executing as soon as we tried to kill the JVM using Ctrl+C command.
    如上图所示,当我们尝试使用Ctrl + C命令杀死JVM时,shutdown挂钩就开始执行。
  2. Program executed normally.Notice that hook is called in case of normal exit too, and it’s printing status as finished.
    请注意,如果在正常退出的情况下也调用了钩子,则其打印状态为完成。
  3. Kill Command to terminate JVM.I used two terminal windows to fire kill command to the java program, so operating system terminated the JVM and in this case shutdown hook was not executed.
    我使用了两个终端窗口向Java程序发射kill命令,因此操作系统终止了JVM,在这种情况下,未执行关闭钩子。

That’s all for shutdown hook in java, I hope you learned about JVM shutdown hooks and might find a use for it.

这就是Java中的关闭钩子,我希望您了解了JVM关闭钩子,并可能会找到用处。

Reference: API Doc

参考: API文档

翻译自: https://www.journaldev.com/9113/java-shutdown-hook-runtime-addshutdownhook