How do I use swing in a shutdown hook? - java

Is there any possible way to add swing into a shutdown hook (that is, display a popup upon the VM shutting down)?
I realize that if I try to make a new JFrame, it will give me an error, as it tries to register a shutdown hook, which fails as the VM is already shutting down. I'm just wondering if there is in fact any way around this

You really shouldn't be doing this. From the Runtime.addShutdownHook specification:
The Java virtual machine shuts down in response to two kinds of events:
The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
...
Shutdown hooks run at a delicate time in the life cycle of a virtual machine and should therefore be coded defensively. They should, in particular, be written to be thread-safe and to avoid deadlocks insofar as possible. They should also not rely blindly upon services that may have registered their own shutdown hooks and therefore may themselves in the process of shutting down. Attempts to use other thread-based services such as the AWT event-dispatch thread, for example, may lead to deadlocks.
Shutdown hooks should also finish their work quickly. When a program invokes exit the expectation is that the virtual machine will promptly shut down and exit. When the virtual machine is terminated due to user logoff or system shutdown the underlying operating system may only allow a fixed amount of time in which to shut down and exit. It is therefore inadvisable to attempt any user interaction or to perform a long-running computation in a shutdown hook.
...
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.
Specific warnings here that suggest you not do this:
"Shutdown hooks should also finish their work quickly."
Relying on anything that might take a while to do its work, or blocking indefinitely on user-input like JOptionPane dialogs, is not what you should be doing in your shutdown hook.
"Attempts to use other thread-based services such as the AWT event-dispatch thread, for example, may lead to deadlocks"
Swing runs on-top of AWT, whose underlying event-dispatch thread may be in the process of shutting down, too. Trying to use Swing or AWT while shutting down can lead not only to dead locks but also may just not work at all, anyways.
"If the virtual machine aborts then no guarantee can be made about whether or not any shutdown hooks will be run"
There are no guarantees your user could even possibly get your message, since shutdown hooks are only guaranteed to run when it exits normally or terminated -- not when halted or aborted.

Shutdown hooks are supposed to execute as quickly as possible. That does not include waiting for a user to confirm a dialog. In any case you have no guarantee that the Swing event thread is still running.
You can't do this.

If there is, it won't help you.
The shutdown hooks are invoked asynchronously as part of the JVM shutdown, so a "confirm" dialog won't really confirm anything as you can't halt or reverse the shutdown process. Waiting for a user to make a decision is not the kind of action a shutdown hook is meant for. A shutdown hook in an interactive program does not make sense.
The real use case for shutdown hooks is:
for releasing resources and other housekeeping when the JVM shutsdown
It is also important to note the shut down hook wont always be run, for more see my answer here: How to shutdown java application correctly from C# one

Swing GUI must be done on Event Dispatch Thread, then
Create JDialog or JOptionPane on Initial Thread
Show Container
Call for Shutdown Hook
Simple way, but required end user action (close JDialog)

I'm not sure about your question, but I think its impossible to run or display a popup window when JVM is shutting down. Its like your trying to run while preparing to sleep? Just guessing. :)

Related

Linux Shutdown and Java Shutdown Hook

When I run a Java process in background and I shut down the computer (ArchLinux), will the computer wait some seconds for the termination of my shutdown-hook in Java?
In case you want to do something on system shutdown, you need to add a shutdown-hook (assuming you already do this) :
Runtime.getRuntime().addShutdownHook(
new Thread(new Runnable() {
#Override
public void run() {
// This method will be executed and Virtual Machine will close when this method will return
}
}));
The system will NEVER await a full termination if it took too much time
From the doc Runtime#addShutdownHook
When the virtual machine is terminated due to user logoff or system shutdown the underlying operating system may only allow a fixed amount of time in which to shut down and exit. It is therefore inadvisable to attempt any user interaction or to perform a long-running computation in a shutdown hook.
A shutdown hook will be called when a call to close the JVM is made. However, there is no guarantee that the hook will be called. The hook might not/won't run:
If the JVM crashes from an internal error.
If SIGKILL is signaled, or kill -9 in linux and TerminateProcess in windows.
The Runtime.halt() will also prevent a hook from begin run.
The computer power is pulled (at the plug).
Your OS crashes.
When the user turns off the computer (not by pulling the plug), the computer sends a shutdown command to the JVM which will execute the shutdown hooks, although if the power is pulled the computer won't have any time to do anything, let alone issue a command to the JVM.
I remember reading somewhere (but i couldn't find the link again) - it said that a shutdown hook shouldn't take to much time to execute or windows might kill it when the system wants shutdown. This indicates that the shutdown hooks will be run if you decide to turn off the system though the OS.
Tl;dr: It depends, pulling the power directly or if the OS crashes, they won't be run. A normal OS shutdown will run the hooks, although it's possible the OS might close them before they finish if they're taking too long.
This is from the javadoc.
When the virtual machine is terminated due to user logoff or system shutdown the underlying operating system may only allow a fixed amount of time in which to shut down and exit. It is therefore inadvisable to attempt any user interaction or to perform a long-running computation in a shutdown hook.
This states that the hooks will be run when the OS wants to shutdown, but it's advised that they don't take long or they might get killed.
You can wrap your java program as a service and it will started and shut down with OS. One of the easiest way to do so, is using spring boot framework.

What are the differences between Stage.setOnCloseRequest() and Runtime.addShutdownHook()?

When writing a JavaFX application, you can provide a shutdown hook to any javafx.stage.Stage with the setOnCloseRequest(EventHandler<WindowEvent>) method. If you do that with your main JavaFX Scene, it serves as an application shutdown hook, and can be used to safely save/release important system resources, etc. But the same (or something very similar) is achieved if you implement a java.lang.Thread and add it as a shutdown hook with Runtime.getRuntime().addShutdownHook(Thread) method.
What are the differences between those approaches. Both work if I call Platform.exit()? Both work if I call System.exit(int)? Which one is considered the safest (meaning, that better ensures saving/releasing system resources) approach? Are there better ways, other than those that I should consider?
These are fundamentally different things.
A handler specified for a particular stage with setOnCloseRequest() will be executed when the user requests to close that particular stage (typically by pressing the OS-specific "close" button in the window). It is invoked on the FX Application Thread, and will be called before the window actually closes. It's execution does not imply that the application is exiting, that the FX toolkit is being closed down, or that the Java Virtual Machine is exiting. A handler here may not only assume the FX toolkit is still running, but may modify the UI (since it is on the FX Application Thread) and may veto the request to close the window by consuming the event.
A shutdown hook is a user-provided thread that is executed when the Java Virtual Machine exits. It is its own thread, and is executed as part of the shutdown sequence. As such, it must not assume any other services are running. From the API docs:
They should also not rely blindly upon services that may have
registered their own shutdown hooks and therefore may themselves in
the process of shutting down. Attempts to use other thread-based
services such as the AWT event-dispatch thread, for example, may lead
to deadlocks.
The same caveat that applies to the AWT event dispatch thread also applies to the FX Application Thread.
In some very specific circumstances, the invocation of a setOnCloseRequested handler may indicate that the JVM may soon be about to exit. These circumstances include all of the following, but I may have omitted something:
The handler does not consume the event
The stage is the last stage left open
Platform.isImplicitExit() returns true
No non-daemon threads are running, and none are started by the Application instance's stop() method
Which you should use depends entirely on what you are trying to do. If the aim is to release resources started as part of you JavaFX Application that are only no longer needed when the application exits, I would not use either of these, but would override the Application.stop() method.

Is there is an oposite tool to static initializer in Java

Static blocks are executed when class is loading even before the public static void main starts. Is there any possibility to run a certain code just before the program close?
I think you're looking for Runtime.addShutdownHook. It's not a language level construct in the way that static initializer blocks are, but I think it'll do what you want.
You should be careful with shutdown hooks though - see the documentation for various warnings around them.
From Runtime.addShutdownHook:-
Just to add a point to Jon Skeets answers
A shutdown hook is simply an initialized but unstarted thread. When
the virtual machine begins its shutdown sequence it will start all
registered shutdown hooks in some unspecified order and let them run
concurrently. When all the hooks have finished it will then run all
uninvoked finalizers if finalization-on-exit has been enabled.
Finally, the virtual machine will halt. Note that daemon threads will
continue to run during the shutdown sequence, as will non-daemon
threads if shutdown was initiated by invoking the exit method.
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.

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

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

Handling abnormal Java program exits

Suppose I have a Java application that opens a database connection. Normally I would add a connection.close() in a finally block, but this block wouldn't be executed in the case of a kill operation, or any other abnormal termination, would it? Are there any other precautions that I, as a programmer, can make in order to close the connection properly before the application exits?
You should look at the Runtime.addShutdownHook() method for Java (http://java.sun.com/javase/6/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)). It allows you to add a hook that will be called when the virtual machine terminates. You can use it to call a cleanup routine.
That would be for a TERM signal though. A KILL signal will kill the process and not allow it to do any cleanup (because the KILL signal cannot be caught or ignored by the receiving process).
If something external kills your program, there's nothing you can do about it. Obviously they wanted to stop it, so how can you prevent them?
I was going to suggest a shutdown hook, but the Javadocs state:
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.
(emphasis mine)
Killing a program will eventually timeout a TCP stream from your program to your [Oracle|SQL Server|MySQL|PostgreSQL] server.
The server will see it and rollback any pending transactions.
You shouldn't need to call connection.close() on application shut-down, since all open files will be closed automatically by the operating system.
Also, the Connection's finalize() method should be run before application shut-down automatically (if the shut-down is normal, not ABORTed), and that should close the connection.
In any case, you can register shutdown-hooks, to do any clean-up you require (again, will be run in normal shutdown cases, not ABORTs).
When you really get killed (kill -9 on UNIX), you can not do anything against that.
A finally-block is the most you can do, see SO: In Java, is the “finally” block guaranteed to be called (in the main method)? for details.
Some level of abnormal termination is unavoidable. How would you catch the event of the power cable being pulled on the server?

Categories

Resources