47

What is the best way to capture a kill signal in java without using JNI. I did discover the sun.misc.Signal and the sun.misc.SignalHandler and the warning of the possibility of being removed in the future releases.

Would using JNI to call a c lib be the only option i have?

166_MMX
  • 590
  • 5
  • 18
Begui
  • 2,726
  • 3
  • 22
  • 17
  • Related: [Catching Ctrl+C in Java](https://stackoverflow.com/questions/1611931/catching-ctrlc-in-java) – ggorlen Oct 23 '21 at 20:07

3 Answers3

66

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.

ugo
  • 2,705
  • 2
  • 30
  • 34
  • 12
    `SIGKILL` (9) is a non catchable signal. That's a Unix design feature. – dolmen Sep 06 '12 at 12:11
  • The `Runtime` class is `java.lang.Runtime` and exists since JDK 1.0. The `addShutdownHook` method exists [since 1.3](http://docs.oracle.com/javase/1.3/docs/api/java/lang/Runtime.html#addShutdownHook%28java.lang.Thread%29). So you can safely rely on them. – dolmen Sep 06 '12 at 14:18
  • 1
    @dolmen read for comprehension, I am warning about the `com.sun` packages, that are mentioned in the question as to not be used. –  Sep 06 '12 at 14:43
  • `SIGKILL(9)` causes the virtual machine to abort and according to the docs: `If the virtual machine aborts then no guarantee can be made about whether or not any shutdown hooks will be run.` http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#addShutdownHook%28java.lang.Thread%29 – adino May 13 '15 at 16:07
  • Just for the record: `com.sun.*` classes *are* usable and maintained, unlike `sun.*` classes (note the `com.` prefix). – Matthieu Jun 11 '21 at 15:16
7

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

delitescere
  • 786
  • 6
  • 5
  • How should we go about implementing these handlers when we've launched using `-Xrs`? – Aly May 11 '19 at 22:48
4

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.

Asgeir S. Nilsen
  • 1,137
  • 9
  • 13
  • 1
    This is for the entire system shutdown though. While it works in most cases, ideal would be if it worked on the inherited process. – mjs Jun 01 '20 at 21:47