문제

I have a rather complicated shutdown in Java - there's a lot of clean up work to do. In particular I'm trying to figure out how to error handle from a shutdown hook thread. My code includes this currently:

try {
    return shutdownPromise = doShutdown();
}
catch (Throwable exc) {
    logger.error("An exception was thrown while shutting down the application.", exc);  
    System.exit(1);
    return null;
}

When I originally wrote this I essentially thought, an error in shutdown should just go straight to exit. But exit is not so low level; it calls the shutdown hooks.

So I thought -

  1. What does calling exit from a shutdown hook do?
  2. What is the right way to error handle from a shutdown hook?
도움이 되었습니까?

해결책

Firstly, the easy answer: your process deadlocks.

System.exit winds up calling Shutdown.exit, which ends with this code block:

synchronized (Shutdown.class) {
     /* Synchronize on the class object, causing any other thread
      * that attempts to initiate shutdown to stall indefinitely
      */
     sequence();
     halt(status);
}

The comment is completely accurate. But to understand this we need to see exactly what the the shutdown hook does.

Shutdown hooks are added via ApplicationShutdownHooks.add, as explained in this answer here. Note that the sequence method above eventually winds up on this line of code in 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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top