Is there a way to delay a windows shutdown with Java?
I always have the problem, that the system is killing the JVM before my ShutdownHook ran through completely.
Annotation:
I have to perform action on a remote server when the system shuts down. This taked a while and I dont have the possibility to change the servers behaviour.
Related
I have a Windows Service, which "controls" a java-based application. In case of terminating the windows service, the java application should close as fast as possible. This killing procedure works, but not in a fast time.
So, for me, there are multiple possibilities: Either the java-app does not recognize directly this "termination command" or any kind of corba-interface, which is used inside of the java-app blocks the termination procedure for 30-60 seconds.
Are there any advices, of how to kill such a java based application at the moment, when terminating the windows service (the current state of the interfaces do not matter, they can be killed as well)?
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.
There is a an answered question on Best Way to Gracefully Shutdown a Java Command Line Program. A shutdown hook does the job in case when a program was terminated by Ctrl+C.
My question is how to gracefully exit if the command line itself is closed during the execution of a Java program? I tested with shutdown hook but it didn't work in this case. I cannot find out what happens to the virtual machine in this scenario. Is the process and all its threads killed instantly?
What kind of signal does closing command line produce?
So, how this particular problem can be solved?
EDIT: The problem concerns Windows environment.
Logically, SIGHUP (terminal hangup) should be raised.
Actually, I've just checked my guess with a simple shell script. Yes, when a user closes a terminal emulator in which an application was started (and from which it wasn't detached), then the application receives SIGHUP. So set up a SIGHUP handler and react accordingly. A usual behaviour is to terminate an application, but your intents may be different.
Also if your Java application performs any STDIN/STDOUT operations, it should be closed or at least re-cofigured when HUP is received, because an attempt to read/write from non existing terminal would lead to SIGPIPE and/or program block.
For Windows take a look at Catch Windows terminal closing on running process
Edit for windows environment:
I don't have much experience on windows environment but if you want your application to keep running, it's generally deployed as Windows service (it's similar to daemon on Linux). You would typically start/stop/restart service through a utility that lists all services (I think you get to it via control panel -> Administrative Tools -> Services. I would guess that issuing a "stop" via this tool would signal a graceful shutdown. And if you kill the service via the task manager, then it won't be a graceful shutdown.
Is this a Linux based or Windows based environment? In Linux, if you ran the program in background (and exit the shell with 'exit' command), it'll continue running. You can put your application in the background by adding an & at the end. Also, a lot of applications/services run in the background. If you execute a Tomcat startup script with the startup.sh command, it'll continue running in the background even when you quit the terminal you launched it from. On windows too, the concept should be similar.
In terms of closing application, you use kill command on Linux systems. kill command on a process sends a SIGTERM signal to it. Applications can implement code to intercept SIGTERM and shutdown gracefully on detecting a SIGTERM. If the application doesn't handle SIGTERM gracefully, then it won't respond to a SIGTERM / kill. In that case, you need to explicitly give it a SIGKILL (kill -9) to kill it forcefully. In that case, graceful shutdown is not possible.
In Java, there is a special Runtime method for that : addShutdownHook.
This allows you to initialize a thread that the JVM will try to run just before stopping. It is the place to put any cleanup you want to execute even in case of Ctrl-C of closing of parent window. Extract from javadoc : 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.
The shutdown hook is call even if the program ends normally. In that case, it is cleaner to remove the registered hook before exiting with removeShutdownHook (still a method from Runtime)
EDIT :
In the case of Windows environment, there are no real signals, but special callbacks when system is shutting down. AFAIK, the system hook is correctly called in that case, but I admit I never really tested that. In Windows, processes can be asked to terminate with 2 ways :
PostQuitMessage function posts a WM_QUIT message in process event loop - normally the process should exit, but it can do its cleanup (equivallent of Unix SIG_TERM)
TerminateProcess immediately stops the process and all its threads (equivallent of Unix SIG_KILL)
Console processes can use a ConsoleControlHandler that can intercept Ctrl-C, Ctrl-Break or Ctrl-Close events. First two are generated through keyboard, last is generated when the user closes the console. But normally, the Oracle JVM should use the system hook mechanisme when getting the Ctrl-Close event that is processed the same as a SIGTERM.
I have an Java application that is started via a batch-script to set environment variables etc.
All works fine with Win7, but on Windows 8 the process doesn't stop completely and stays in background as I can see the javaw-process in the taskmanager. Then when starting the application again a second javaw-process starts.
I need the application to stop completely. Is there a way to do this in the application's shutdown procedure in Java code or are there settings in Win 8 to prevent this behaviour for Java? Or exists a commandline argument to pass when starting a process/java?
For clarification: There seems to be a new Windows 8 feature, that on close of an application the processes are just halted and the process will re-awake when the app is called again. But my legacy application does not support such re-awaking so I want to completely close the application and cleanly re-start it on the next call. For closing I currently call System.exit(), but regretably that's not enough and the process is in a state where it is neither dead nor alive but in a "sleeping mode".
I would suggest debugging the application on the Windows 8 system and look at what is happening in the code where you expect the application to shut down. It might be waiting on a specific resource.
If needed you can always execute System.exit() to force a shut down.
Is there any way to make the program go through the shutdown hook if the user forces java to close (through the task manager or by closing the corresponding batch file).
My program currently runs and executes well, if the user closes the GUI then it goes through a set of steps to disconnect from the database. However, if the user closes the Java or the batch file (running side by side with the GUI) then the connection to the database isn't closed.
Is it possible to somehow force the connection closed and maybe even delete something from the tables? The batch file will probably not be an issue when I jar the program but the process killing still will.
Nope.
The shutdown hook will react to Ctrl+C, normal closes, user logouts, and normal system shut downs (which request a graceful shutdown of all applications).
However, if someone is force-closing the app it's assumed that that's what you actually want - immediate termination with no further notice. This question has been asked many times, and is confused by the behavior of many applications that, when they are asked to force-close, they actually take a long time to finally terminate. This is because in the OS's efforts to release all resources, some resources (especially certain I/O and/or file resources) don't let go immediately.
In testing an app that starts, and is intended to be running until a graceful shutdown (e.g. server software) you should run it at the console/command-line, and press Ctrl+C to stop the program (which will run the shutdown hook) rather than using Task Manager, or KILL -9.
Furthermore, there's nothing Java could even do about it if it wanted to. A force-close happens at the OS level, at which point it releases the memory, file and I/O handles in use, etc. Java does not (nor does any other program) have control over a force-close. At this point, the OS is taking charge.