Home » Java » How to ensure a piece of code is run before exiting a java application

How to ensure a piece of code is run before exiting a java application

Posted by: admin December 28, 2021 Leave a comment

Questions:

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?

Answers:

@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.

###

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.

###

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 the TerminateProcess 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.

###

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();
 }