首先,简单的答案:您的进程死锁。
System.exit 结束调用Shutdown.exit
,以这个代码块结束:
synchronized (Shutdown.class) {
/* Synchronize on the class object, causing any other thread
* that attempts to initiate shutdown to stall indefinitely
*/
sequence();
halt(status);
}
评论完全准确。但要理解这一点,我们需要确切了解关闭挂钩的作用。
关机钩子是通过添加的ApplicationShutdownHooks.add
,正如这里的答案中所解释的那样。请注意,sequence
上面的方法最终会在以下代码行中结束Shutdown.runHooks
:
if (hook != null) hook.run();
Firstly, note these hooks are not your application shutdown hooks. They are system shutdown hooks, which are different, and one of them is responsible for ensuring your application shutdown hooks run. Notice that is run, not start. In other words, it blocks. One of these shutdown hooks will be a system hook that concurrently starts all the application shutdown hooks (you can trace this code for yourself or in linked answer), then blocks until they all complete using a Thread.join
call. One of these will be your application shutdown hook - which, if it calls System.exit
, will be waiting to get the lock on Shutdown.class
forever.
Next, the dumb answer: call Runtime.getRuntime().halt()
instead. I say "the dumb answer" because this is probably the slightly lower level thing you were looking to do instead of exit. If System.exit
represents a clean shutdown that failed, then halt
is a hard shutdown that will always succeed immediately.
Next, the smarter answer: probably nothing. Just let your shutdown hook finish, for the following reasons. Your shutdown hook does not own the shutdown - in particular, there may be other shutdown hooks that need to do their work. Conversely, I suspect one of the responsibilities of this hook is to force a hard shutdown eventually. I would recommend creating that as a delayed task right away then letter this hook complete normally.