Capture SIGINT in Java

Solution 1:

The way to handle this would be to register a shutdown hook. If you use (SIGINT) kill -2 will cause the program to gracefully exit and run the shutdown hooks.

Registers 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.

I tried the following test program on OSX 10.6.3 and on kill -9 it did NOT run the shutdown hook, didn't think it would. On a kill -15 it DOES run the shutdown hook every time.

public class TestShutdownHook
{
    public static void main(final String[] args) throws InterruptedException
    {
        Runtime.getRuntime().addShutdownHook(new Thread()
        {
            @Override
            public void run()
            {
                System.out.println("Shutdown hook ran!");
            }
        });

        while (true)
        {
            Thread.sleep(1000);
        }
    }
}

This is the documented way to write your own signal handlers that aren't shutdown hooks in Java. Be warned that the com.sun.misc packages and are un-supported and may be changed or go away at any time and probably only exist in the Sun JVM.

Solution 2:

Since at least Java 6, the HotSpot java command has had a -Xrs flag to disable the JVM signal handlers.

If you use it, you need to implement your own SIGINT, SIGTERM, SIGHUP, and SIGQUIT handlers, including one to explicitly call System.exit().

Note: this means the thread dump facility of SIGQUIT is disabled when the -Xrs flag is present.

See https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html#BABHDABI (also available on the Windows and Solaris java counterparts).

Solution 3:

Take a look at Integrating Signal and Exception Handling describing the HotSpot JVM's ability do do signal chaining. It does involve some C-level trickery though.

Wouldn't java.lang.Runtime.addShutdownHook(Thread) be enough for your purpose? These hooks are run by the JVM upon termination, including reception of SIGINT, as long as the JVM is able to perform them.