问题
I'm using a licensed API which has a method to acquire/release a license object from a license server that has a finite number of licenses. At the beginning of my application, I call the method to acquire the license, but I want to make sure that this gets released even if my program terminates/crashes abruptly (exceptions, SIGTERM, etc). Is the shutdown hook the best way to approach this issue?
回答1:
@thedan is correct about hard JVM crashes. If a JVM crashes hard or it gets a SIGKILL, it won't get a chance to run anything before exiting. There is nothing you can do to remedy this in Java in that scenario. (But the situation is the same in other languages too ...)
However if the JVM does an orderly shutdown in response to all non-dameon threads ending, calling System.exit(), getting a SIGINT and so on, then the JVM will attempt to run the shutdown hooks. There is more information on Java's shutdown hook mechanisms in the Q&A page and the javadocs.
The finally
approach is also an option, but is only works if the thread in question is terminated before the JVM exits. This won't happen if System.exit()
is called or the JVM is terminated by a signal. Shutdown hooks work in more situations.
(To my mind, finally
is really for performing clean on a single thread rather than for the entire application. However if your application consists of just one thread ... or if it has a master thread that is responsible for orderly shutdown ...then finally
can serve the purpose of application cleanup.)
The real solution is to configure the licensed API so that the license manager can detect when the application instance using a license goes away without releasing it. Whether this is possible depends on the license manager.
回答2:
If the program is terminated through a crash of the JVM, you can't rely on anything being called.
If the program is terminated through an exception that doesn't involve the JVM you should be able to wrap everything in a try/catch/finally block. Any code in the finally block would be guaranteed to run before your code exits.
回答3:
For exceptions, you can wrap the body of main
in a try/catch/block
. For handling the SIGTERM
signal, you can add a shutdown hook. However, the shutdown hook is not guaranteed to get triggered for a signal like SIGKILL
.
From Java doc:
In rare circumstances the virtual machine may abort, that is, stop running without shutting down cleanly. This occurs when the virtual machine is terminated externally, for example with the
SIGKILL
signal on Unix or theTerminateProcess
call on Microsoft Windows. The virtual machine may also abort if a native method goes awry by, for example, corrupting internal data structures or attempting to access nonexistent memory. If the virtual machine aborts then no guarantee can be made about whether or not any shutdown hooks will be run.
回答4:
you achieve this by never calling Sytem.exit(). In main() you create a "last line of defense" with
try {
startApp();
} catch (Exception ex) {
// do some logging
} finally {
releaseLicense();
}
来源:https://stackoverflow.com/questions/13754263/how-to-ensure-a-piece-of-code-is-run-before-exiting-a-java-application