正确地kill java进程

在linux/unix下,你会怎么中止一个java进程?
你可能会回答 kill -9 pid,这是一种在多数情况下正确的做法。不过,这种方式过于暴力,如果用户对环境不熟悉,很容易造成致命的后果。
本文将分析kill -9产生问题的原因,并给出另一种标准的kill方式。

标准中断信号

在Linux信号机制中,存在多种进程中断信号(Linux信号列表)。其中比较典型的有 SIGNKILL(9) 和 SIGNTERM(15).

SIGNKILL(9) 和 SIGNTERM(15) 的区别在于:
SIGNKILL(9) 的效果是立即杀死进程. 该信号不能被阻塞, 处理和忽略。
SIGNTERM(15) 的效果是正常退出进程,退出前可以被阻塞或回调处理。并且它是Linux缺省的程序中断信号。

由此可见,SIGNTERM(15) 才是理论上标准的kill进程信号。
那使用 SIGNKILL(9) 又有什么错呢?

SIGNKILL(9) 带来的问题

先看一段程序

/**
 * Shutdown Hook Presentation
 *
 * @author Ken Wu
 */
public class ShutdownHookTest {
 
	private static final void shutdownCallback() {
		System.out.println("Shutdown callback is invoked.");
	}
 
	public static void main(String[] args) throws InterruptedException {
		Runtime.getRuntime().addShutdownHook(new Thread() {
 
			@Override
			public void run() {
				shutdownCallback();
			}
 
		});
		Thread.sleep(10000);
	}
 
}

在上面这段程序中,我使用Runtime为当前java进程添加了一个ShutdownHook,它的作用是在java正常退出时,执行shutdownCallback()这个回调方法。
此时,如果你试验过在java进程未自动退出前,执行 kill -9 pid,即发送 SIGNKILL 信号,会发现这个回调接口是不会被执行的。这是SIGNKILL信号起的作用。

对于我这个简单的测试用例来说,不被执行也无大碍。但是,如果你的真实系统中有需要在java进程退出后,释放某些资源。
而这个释放动作,因为SIGNKILL被忽略了,那就可能造成一些问题。

所以,推荐大家使用标准的kill进程方式,即 kill -15 pid。

转载请注明原文链接:http://kenwublog.com/kill-java-correctly

2009/11/04 | Posted in Development Skills
  1. 2009/11/04 20:55 | #1

    懂了,谢谢啦,之前都是使用 9 这个信号量的

    • 2009/11/04 21:39 | #2

      其实大部分人都是用9的,包括此前的我。大家都忽视了这个9带来的问题。

  2. 2009/11/05 17:38 | #3

    kill -9 貌似干掉进程后,有些资源不能released

  3. 2009/11/07 09:31 | #4

    过来支持一下

  4. happy blue
    2009/11/08 21:22 | #5

    其实使用9都是为了节省时间,能即时响应

  5. 2009/11/08 23:08 | #6

    happy blue :

    其实使用9都是为了节省时间,能即时响应

    对,只不过在使用前,需要考虑自己程序中是否使用了类似ShutdownHook的信号处理器。

  6. littleJava
    2010/02/05 11:28 | #7

    在一个多线程程序中,如果直接使用 kill -9 pid,会导致线程操作结果的丢失吧?!

  7. sking
    2010/09/21 16:12 | #9

    先学习了!以后用到时再拿出来用!哈

  8. Anonymous
    2011/03/18 14:50 | #10

    Ken Wu :
    是的。强制中断进程是毁灭性的。

    依赖于捕获信号来保证程序的正确性才是毁灭性的

    • 2011/03/28 16:11 | #11

      这已经不是信号本身的问题了!也请了解使用场景。
      如果仅仅是依靠信号来保障程序正确性,只能说应用的可用性没考虑全面。
      任何一个可用性保障都不应该吊死在一棵树上。

  9. Yu Li
    2011/06/18 15:15 | #12

    受教了!以前用kill -9 pid结束进程,偶尔会导致defunct僵死进程,也没有深究,原来是这么回事

Leave a comment

Attention: Java syntax highlighting is enable. For example: <pre lang="java"> class A {} </pre>