Exiting an application gracefully? - java

I have an application with a well defined Try/Catch/Finally chain that exits and executes the finally block just fine under normal conditions, however when someone prematurely hits the red X in the GUI, the program fully exists (code = 0) and the main thread's finally block isn't called.
In fact, I do want the program to exit upon a click of the red-X, but what I do not want is a skipping of the finally{} block! I sort of put in the most important part of the finally block manually in the GUI but I really do not want to do it this way since I want the GUI decoupled from the actual program:
class GUI { // ...
...
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
try {
processObject.getIndicatorFileStream().close();
} catch (Exception ignore) {}
System.exit(0);
}
});
...
}
But I'd prefer to just have a call like this:
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
And make sure that all the finally{} blocks get called from each thread after the Exit.
I know this is actually expected. If the application is closed from a separate thread (say the GUI thread) then the main thread will just stop in its tracks.
In short -- how do I ensure that a System.exit(0) or a JFrame.EXIT_ON_CLOSE will still cause each thread's finally block to execute?

If you have no other design change choices then what you may need is a JVM shutdown hook, which can be added to run a piece of code when System.exit is called.
Shutdown Hooks are a special construct that allow developers to plug
in a piece of code to be executed when the JVM is shutting down. This
comes in handy in cases where we need to do special clean up
operations in case the VM is shutting down.
You can add a shutdown hook as mentioned here:
Runtime.getRuntime().addShutdownHook(Thread)
Read more about shutdown hooks here:
http://java.dzone.com/articles/know-jvm-series-2-shutdown
Word of Caution:
We must keep in mind is that it is not guaranteed that shutdown
hooks will always run. If the JVM crashes due to some internal error,
then it might crash down without having a chance to execute a single
instruction. Also, if the O/S gives a SIGKILL
(http://en.wikipedia.org/wiki/SIGKILL) signal (kill -9 in Unix/Linux)
or TerminateProcess (Windows), then the application is required to
terminate immediately without doing even waiting for any cleanup
activities. In addition to the above, it is also possible to terminate
the JVM without allowing the shutdown hooks to run by calling
Runime.halt() method.

If you happen to have such threads which can legally be stopped at any time, at any point at all within their loop, at any point within any method which they invoke, and may I warn you that it is very unlikely that you do, then you can stop all of them upon program exit. This will result in an exception being thrown in each thread, and the finally blocks will execute.
However, the proper way to achieve your goal and have GUI decoupled from the program logic, is to issue a single "exit" signal from the GUI, which will trigger all the application cleanup, which is written in an entirely different class. If you have running threads, then implement the interrupt mechanism in each of them.
There are many ways to achieve the exit signaling. For example, your business code could register a GUI listener for a special event, which would trigger the cleanup. You could also have a thread which doesn't do anything else but await on a CountDownLatch which would be countDown from the GUI.
Please, do not at any cost use a shutdown hook. This is the dirtiest mechanism imaginable, and it is there only as a last resort, when all regular cleanup procedures fail. It is never to be used as a part of the regular shutdown routine.
In summary, there is no royal way to clean application shutdown. You must implement specific mechanisms for each specific concern.

With modern Java, Window.dispose() on all application windows can offer more graceful possibility to exit an AWT application than System.exit(0), see
https://docs.oracle.com/javase/8/docs/api/java/awt/Window.html#dispose--
/** Listens and closes AWT windows.
* The class is implemented as singleton since only one is needed.
*/
public class ExitListener extends WindowAdapter {
/** the instance object */
private static final ExitListener INSTANCE = new ExitListener();
// hide the constructor
private ExitListener () {}
/** retrieve the listener object */
public static ExitListener getInstance () {
return INSTANCE;
}
#Override
public void windowClosing ( final WindowEvent e ) {
e.getWindow().dispose();
}
}
and with your windows
window.addWindowListener( ExitListener.getInstance() );
However, be careful in adverse environments, see:
https://docs.oracle.com/javase/8/docs/api/java/awt/doc-files/AWTThreadIssues.html#Autoshutdown

Related

Code not reaching "finally" block

The given java code is not going to the finally block, I thought these blocks were supposed to execute no matter what:
public static void main(String[] args) {
try {
System.out.println("Hello world");
System.exit(0);
} finally {
System.out.println("Goodbye world");
}
}
System.exit(0);
will unload the JVM i.e no further java instructions are processed
That is the reason for not being exicuting the finally{}
As stated in the Java 6 System.exit() docs:
The call System.exit(n) is effectively equivalent to the call: Runtime.getRuntime().exit(n)
And, if you go and look at Runtime.exit() (my bold):
Terminates the currently running Java virtual machine by initiating its shutdown sequence. This method never returns normally.
The virtual machine's shutdown sequence consists of two phases. In the first phase all registered shutdown hooks, if any, are started in some unspecified order and allowed to run concurrently until they finish. In the second phase all uninvoked finalizers are run if finalization-on-exit has been enabled. Once this is done the virtual machine halts.
Basically, the only one this function can return (and hence allow the finally clause to run) is for it to raise a SecurityException because whatever security manager is running disallows exiting with the given code.
Yes, that's normal. The finally blocks is always executed, except in the case where the JVM is stopped before reaching the end of the code, which is your case here, as you exit the JVM.
The System.exit method stops the execution of the current thread and all others threads.
The presence of a finally does not give a thread special permission to continue executing.
A previous discusses this in great detail.
How does Java's System.exit() work with try/catch/finally blocks?
By System.exit(0) You are exiting from Jvm so no lines after this will get executed and That's why you are finding your finally block as unexecuted.

Java static TimerTask shutdown

I have a static, periodic, java Timer/TimerTask that I would like to shutdown when the app does. I don't want the app hanging because some thread is still running (like what happens in debug mode in eclipse, some environments may kill the thing anyway). The reason I have it static is I plan to have some (very simple, probably just a counter) shared memory in all of the containing class's instances with the Timer so I feel class scope is appropriate.
My question is how best to do the shutdown of the Timer? Is this an appropriate time to use finalize? This timer seems benign enough that having a non-deterministic call to finalize may work? Would probably need to do some kind of instance counting to verify that there are no longer any instances of the class out there? Suggestions on ways to manage the shutdown of the static Timer are welcome.
pseudo code:
class foo {
private static Timer someTimer = null;
public foo() {
if(someTimer == null) {
someTimer = new Timer(new TimerTask(...));
}
}
//how should I shut this thing down?
protected void finalize() throws Throwable {
}
//or is better to have shutdown() called explicitly?
}
It all depends on what your app actually does, but in general there will be some kind of event to signal that the app is being shutdown. For example if it's a GUI app, then maybe this will be the "user clicked on the Quit button" event. Or it's a webapp based on the servlet API, it will be an event fired by a ServletContextListener.
You should add a listener for this event, which calls some kind of shutdown method on your foo object. Inside this shutdown method the foo should take care of cleaning up its resources, including stopping the timer.
As a last resort, you might want to investigate JVM shutdown hooks

If I type Ctrl-C on the command line, will the finally block in Java still execute?

I'm running my Java application in cmd.exe in Windows. If I stop the process forcefully by pressing Ctrl-C, and the code at that moment was running in the try block, will the finally block still be executed?
In my tests it seems that, yes, it is executed.
The correct way to ensure that some code is run in response to an operating system signal (which is what Ctrl-C does, it sends a SIGINT) is to register a "shutdownHook". Here's a StackOverflow question about handling it, and here's an article with way more detail about the JVM's signal handling than you probably will ever want to know.
While your finally code may have executed on your Windows machine (I couldn't reproduce it with Linux), according to this documentation on finally:
Note: If the JVM exits while the try
or catch code is being executed, then
the finally block may not execute.
Likewise, if the thread executing the
try or catch code is interrupted or
killed, the finally block may not
execute even though the application as
a whole continues.
So I wouldn't use a finally block to make sure a piece of code executes, even if the user tries to prematurely exit. If you need that, you can use, like Adrian Petrescu mentioned, Shutdown Hooks
In my test on Windows 7, Sun Java 1.6, the finally block did not execute if I pressed Ctrl-C during this try block.
public static void main(String[] args) {
try {
for (int i = 0; i < 1000; i++) {
System.out.println(i);
}
}
finally {
System.out.println("finally");
}
}
Depending on OS implementations, generally sigkills are meant to stop applications immediately. In this situation it is not desirable to rely on finally block to execute; it may in some situations, but generally it would/should not. The java.lang.Runtime documentation further supports this:
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.
No, the finally block is not being run for me when I Ctrl-C (in Linux).
I recommend moving your finally logic to a method "shutdown". Then calling it from both the finally block as well as from a Ctrl-C handler. Like this:
private void registerSigIntHandler() {
final SignalHandler defaultSigIntHandler = Signal.handle(new Signal("INT"), SignalHandler.SIG_DFL);
Signal.handle(new Signal("INT"), new SignalHandler() {
public void handle(Signal signal) {
log.info("SIGINT received");
Signal.handle(new Signal("INT"), SignalHandler.SIG_DFL);
shutdown();
defaultSigIntHandler.handle(signal); }
});
}
The benefit of doing it this way is that after shutdown completes, the SIG_DFL handler executes, terminating the program via the default OS SIGINT handler. This terminates the main thread and the entire process. Otherwise, if you do not use SIG_DFL, you have to somehow signal the main thread to exit. My main thread does not listen/poll for shutdown signals/messages. It is a long-running data-migration job. I want to shut down certain things but terminate the main thread and subthreads.
Also if shutdown hangs (hopefully should not happen), a second ctrl-c will terminate the program via the SIG_DFL handler.
In shutdown, I also set an AtomicBoolean to ensure shutdown is only run once.
boolean isShuttingDown = this.isShuttingDown.getAndSet(true);
if (isShuttingDown) {
return;
}
I also tried addShutdownHook (an alternative to Signal.handle) but ran into trouble with it not running my shutdown routine fully. I was messaging and joining with subthreads.
Note: Do not call SignalHandler.SIG_DFL.handle(new Signal("INT"));. It gives me SIGSEGV every time (which does exit the program). - How do I trigger the default signal handling behavior?

How to avoid use of Thread.Sleep

I never gave the use of Thread.Sleep much thought, until I downloaded the latest version of Netbeans. Netbeans now warns you not to use Thread.Sleep. So I did some research on the topic and found people stating that you only need to use Thread.Sleep for debugging/testing purposes and that if you use it at any other time you have poorly written code.
So my question is how can I keep from using Thread.Sleep in the following situation.
I have written a server application that interfaces with another application. The server has two threads:
Handles the data coming over the socket and sends back other information or just plain acknoledgements.
This is the main thread. After kicking off the socket thread it going into an indefinite while loop. Within this while loop I check to make sure the socket thread is still active and that the user hasn't asked to exit the application via a TrayIcon interface. Then I sleep and continue this while loop.
With this application, the TrayIcon is the only UI.
Here is the snippet I'm referencing:
// continues running as long as the exitth file is not present and
// the tray icon is not in a safe to exit status.
while(doNotExit())
{
if (getPrimaryThread() == null || !getPrimaryThread().isAlive())
resetsThreadAndSocket();
try
{
// check to see if the socket threads are still active, if not create new ones.
if ((getPrimaryThread() == null || !getPrimaryThread().isAlive()))
createSocketThread();
// check right before sleeping that the user does not want to exit.
if(getTrayIcon().isExiting())
break;
// puts the main Thread to sleep for 3 seconds
Thread.sleep(3000);
}
catch(SQLException ex)
{
_log.error(ex.getMessage(), ex);
restartDatabase();
}
}
The 'preferred' method in most cases would be to use the ScheduledExecutorService built into JavaSE for performing a periodic task, rather than reimplementing it yourself every time using a while loop and Thread.Sleep().
There's nothing wrong per-se with your example. The language just now has a much more robust support for doing that built into it as of Java 5.
Instead of your Thread.sleep(3000) do:
getPrimaryThread().join(3000)
This will wait for the thread to exit for 3 seconds.
You should consider attaching an event listener to your tray icon instead of polling its state. That way you won't need an extra thread just for monitoring.
If you can't do that for some reason, you can still do away with the extra thread as the Timer class can do the waiting for you.
You seem to be paranoid that some condition (maybe a RuntimeException or Error?) is going to cause your socket Thread to just die. Ideally, you would design your Socket Thread such that it protected itself from crashing. The following example creates a loop that can only be broken as a result of a JVM Error or Thread interrupt:
public void run() {
while(!Thread.currentThread.isInterrupted()) {
try {
//you application logic
} catch (RuntimeException e) {
//log uncaught exception
}
}
}
In order to shutdown the application, you would attach a listener to the TrayIcon which contained a reference to the SocketThread and could stop it by simply interrupting it.
socketThread.interrupt();
I'll leave figuring how to add an ActionListener to a TrayIcon up to you.

What can cause Java to keep running after System.exit()?

I have a Java program which is being started via ProcessBuilder from another Java program.
System.exit(0) is called from the child program, but for some of our users (on Windows) the java.exe process associated with the child doesn't terminate. The child program has no shutdown hooks, nor does it have a SecurityManager which might stop System.exit() from terminating the VM. I can't reproduce the problem myself on Linux or Windows Vista. So far, the only reports of the problem come from two Windows XP users and one Vista user, using two different JREs (1.6.0_15 and 1.6.0_18), but they're able to reproduce the problem every time.
Can anyone suggest reasons why the JVM would fail to terminate after System.exit(), and then only on some machines?
Edit 1: I got the user to install the JDK so we could get a thread dump from the offending VM. What the user told me is that the VM process disappears from VisualVM as soon as he clicks on the 'Quit' item in my menu---but, according to Windows Task Manager, the process hasn't terminated, and no matter how long the user waits (minutes, hours), it never terminates.
Edit 2: I have confirmed now that Process.waitFor() in the parent program never returns for at least one of the users having the problem. So, to summarize: The child VM seems to be dead (VisualVM doesn't even see it) but the parent still sees the process as live and so does Windows.
This can happen if your code (or a library you use) has a shutdown hook or a finalizer that doesn't finish cleanly.
A more vigorous (so should only be used in extreme cases!) way to force shutdown is by running:
Runtime.getRuntime().halt(0);
The parent process has one thread
dedicated to consuming each of the
child's STDOUT and STDERR (which
passes that output through to a log
file). So far as I can see, those are
working properly, since we're seeing
all the output we expect to see in the
log
i had a similar problem with my program not disappearing from task mgr when i was consuming the stdout/stderr. in my case, if I closed the stream that was listening before calling system.exit() then the javaw.exe hung around. strange, it wasn't writing to the stream...
the solution in my case was to simply flush the stream rather than close it before existing. of course, you could always flush and then redirect back to stdout and stderr before exit.
Check if there is a deadlock.
For example,
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
System.exit(1);
and in the close()
public void close() {
// some code
System.exit(1);
}
The System.exit() actually calls the shutdown hook and finalizers. So, if your shutdown hook calls the exit() again internally, for some reason (for example, when the close() raises an exception for which you want to exit the program, then you will call exit() there also). Like this..
public void close() {
try {
// some code that raises exception which requires to exit the program
} catch(Exception exceptionWhichWhenOccurredShouldExitProgram) {
log.error(exceptionWhichWhenOccurredShouldExitProgram);
System.exit(1);
}
}
Though, it is a good practice to throw the exception, some may choose to log and exit.
Note, also, that Ctrl+C will also not work if there is a deadlock.
Since it also calls the shutdown hook.
Anyways, if it is the case, the problem can be solved by this workaround:
private static AtomicBoolean exitCalled=new AtomicBoolean();
private static void exit(int status) {
if(!exitCalled.get()) {
exitCalled.set(true);
System.exit(status);
}
}
Runtime.getRuntime().addShutdownHook(new Thread(MyClass::close));
exit(1);
}
private static void close() {
exit(1);
}
P.S: I feel that the above exit() version must actually be written
in the System.exit() method only (may be some PR for JDK?) Because,
there is practically no point (at least from what I see) in
entertaining a deadlock in System.exit()
Here are a couple of scenarios...
Per the definition of a Thread in http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Thread.html
...
When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class). The Java Virtual Machine continues to execute threads until either of the following occurs:
1) The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
2) All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.
Another possibility is if the method runFinalizersOnExit has been called. as per the documentation in http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html
Deprecated. This method is inherently unsafe. It may result in finalizers being called on live objects while other threads are concurrently manipulating those objects, resulting in erratic behavior or deadlock.
Enable or disable finalization on exit; doing so specifies that the finalizers of all objects that have finalizers that have not yet been automatically invoked are to be run before the Java runtime exits. By default, finalization on exit is disabled.
If there is a security manager, its checkExit method is first called with 0 as its argument to ensure the exit is allowed. This could result in a SecurityException.
Maybe a badly written finalizer? A shutdown hook was my first thought when I read the subject line. Speculation: would a thread that catches InterruptedException and keeps on running anyway hold up the exit process?
It seems to me that if the problem is reproducible, you should be able to attach to the JVM and get a thread list/stack trace that shows what is hung up.
Are you sure that the child is still really running and that it's not just an unreaped zombie process?
Does the parent process consumes the error- and outputstream from the child process?
If under some OS the childprocess print out some errors/warning on stdout/stderr and the parent process is not consuming the streams, the childprocess will block and not reach System.exit();
Hy i had the same problem, but the couse for me was i was using the remote Debugging(VmArgs: -Xdebug -Xrunjdwp:transport=dt_socket,address=%port%,server=y,suspend=y) when i disabled this the java.exe Process exited as expected.
I think all of the obvious causes have been provisionally covered; e.g. finalizers, shutdown hooks, not correctly draining standard output / standard error in the parent process. You now need more evidence to figure what is going on.
Suggestions:
Set up a Windows XP or Vista machine (or virtual), install the relevant JRE and your app, and try to reproduce the problem. Once you can reproduce the problem, either attach a debugger or send the relevant signal to get a thread dump to standard error.
If you cannot reproduce the problem as above, get one of your users to take a thread dump, and forward you the log file.
Another case not mentioned here is if the shutdown hooks hang on something so be careful in writing the shutdown hook code(and if a 3rd party library registered a shutdown hook that is hanging as well).
Dean

Categories