【问题标题】:Why doesn't the main thread run to completion when java receives a kill signal?java收到kill信号后,为什么主线程没有运行完成?
【发布时间】:2019-01-21 13:03:31
【问题描述】:
所以我有这个代码块:
package com.stackoverflow.jontejj.killsignal;
public class Problem {
public static void main(String[] args) {
try {
System.out.println("Executing");
Thread.sleep(1000000);
System.out.println("Done sleeping");
} catch (InterruptedException e) {
System.out.println("Interrupted");
throw new RuntimeException(e);
}
System.out.println("Finished");
}
}
我正在尝试使用
中止主要方法
kill -15 <pid>
我希望它打印“中断”和堆栈跟踪,但程序只是直接被杀死。我应该如何优雅地处理终止信号?
【问题讨论】:
标签:
java
interrupt
kill-process
【解决方案1】:
默认行为记录在Runtime#addShutdownHook:
在极少数情况下,虚拟机可能会中止,即停止运行而不完全关闭。当虚拟机在外部终止时会发生这种情况,例如在 Unix 上使用 SIGKILL 信号或在 Microsoft Windows 上使用 TerminateProcess 调用。如果本地方法出错,例如破坏内部数据结构或尝试访问不存在的内存,虚拟机也可能中止。如果虚拟机中止,则无法保证是否会运行任何关闭挂钩。
要解决此问题并在终止信号上发送中断,您可以执行类似于此的操作:
package com.stackoverflow.jontejj.killsignal;
public class Solution {
public static void main(String[] args) {
Thread main = Thread.currentThread();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
main.interrupt();
main.join(); //Possibly with a timeout here
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
}
}));
try {
Thread.sleep(1000000);
System.out.println("Done sleeping");
} catch (InterruptedException e) {
System.out.println("Interrupted");
throw new RuntimeException(e);
}
System.out.println("Bye");
}
}
这将导致:
Interrupted
Exception in thread "main" java.lang.RuntimeException: java.lang.InterruptedException: sleep interrupted
at java_stopping/com.stackoverflow.jontejj.killsignal.Solution.main(Solution.java:18)
Caused by: java.lang.InterruptedException: sleep interrupted
at java.base/java.lang.Thread.sleep(Native Method)
at java_stopping/com.stackoverflow.jontejj.killsignal.Solution.main(Solution.java:14)
在收到终止信号时打印。