2015年2月25日 星期三

[ Java 常見問題 ] How to gracefully handle the SIGKILL signal in Java

Source From Here 
Question 
How do you handle clean up when the program receives a kill signal? 

For instance, there is an application I connect to that wants any third party app (my app) to send a finish command when logging out. What is the best say to send that finish command when my app has been destroyed with a kill -9

How-To 
The way to handle this for anything other than kill -9 would be to register a shutdown hook. If you can use (SIGTERMkill -15 the shutdown hook will work. (SIGINTkill -2 DOES cause the program to gracefully exit and run the shutdown hooks. 

Regarding to registering a new virtual-machine shutdown hook, the Java virtual machine shuts down in response to two kinds of events: 
* The program exits normally, when the last non-daemon thread exits or 
when the exit (equivalently, System.exit) method is invoked, or

* The virtual machine is terminated in response to a user 
interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.

On a kill -15 it DOES run the shutdown hook every time with below sample code: 
  1. package test;  
  2.   
  3. public class TestShutdownHook {  
  4.     public static void main(final String[] args) throws InterruptedException  
  5.     {  
  6.         Runtime.getRuntime().addShutdownHook(new Thread()  
  7.         {  
  8.             @Override  
  9.             public void run()  
  10.             {  
  11.                 System.out.println("Shutdown hook ran!");  
  12.             }  
  13.         });  
  14.   
  15.         while (true)  
  16.         {  
  17.             Thread.sleep(1000);  
  18.         }  
  19.     }  
  20. }  
There are ways to handle your own signals in certain JVMs -- see this article about the HotSpot JVM for example

By using the Sun internal sun.misc.Signal.handle(Signal, SignalHandler) method call you are also able to register a signal handler, but probably not for signals like INT or TERM as they are used by the JVM. To be able to handle any signal you would have to jump out of the JVM and into Operating System territory. 

What I generally do to (for instance) detect abnormal termination is to launch my JVM inside a Perl script, but have the script wait for the JVM using thewaitpid system call. I am then informed whenever the JVM exits, and why it exited, and can take the necessary action. 

Below are sample code to catch signal SIGHUP(1) and SIGABRT(6) by calling Signal.handle(Signal, SignalHandler)
  1. package test;  
  2.   
  3. import sun.misc.Signal;  
  4. import sun.misc.SignalHandler;  
  5.   
  6. public class SignalTest {  
  7.     public static class TestSignalHandler implements SignalHandler  
  8.     {  
  9.         @Override  
  10.         public void handle(Signal sig) {  
  11.             System.out.printf("\t[Info] Handle Signal: %s(%d)\n", sig, sig.getNumber());              
  12.         }         
  13.     }  
  14.       
  15.     public static void main(String args[]) throws Exception  
  16.     {  
  17.         TestSignalHandler handler = new TestSignalHandler();  
  18.         Signal.handle(new Signal("ABRT"), handler);  
  19.         Signal.handle(new Signal("HUP"), handler);  
  20.         while(true)  
  21.         {  
  22.             Thread.sleep(1000);  
  23.         }  
  24.     }  
  25. }  
Supposed you wrap this class into Test.jar. You can run it in Linux machine to test the functionality: 
$ java -jar Test.jar &
[1] 19034
$ kill -6 19034 # Send signal SIGABRT
[Info] Handle Signal: SIGABRT(6)
$ kill -1 19034 # Send signal SIGHUP
[Info] Handle Signal: SIGHUP(1)
$ kill -2 19034 # Stop program
[1]+ Exit 130 java -jar Test.jar

Supplement 
Wiki - Unix Signal 
Signals are a limited form of inter-process communication used in Unix, Unix-like, and other POSIX-compliant operating systems. A signal is an asynchronous notification sent to a process or to a specific thread within the same process in order to notify it of an event that occurred. Signals have been around since the 1970s Bell Labs Unix and have been more recently specified in the POSIX standard.

Java Code Examples for sun.misc.SignalHandler 
Oracle Document - Integrating Signal and Exception Handling

沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...