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.
Related
I have an application programmed in java, and I need to save a log when it is manually stopped, either by task manager or another party.
If it can be captured by java or by some external windows application, I do not care, I just need the log that says "Hey, your application was stopped manually ..." Thanks!
PS: I have the application in netbeans, and obviously I have many logs in many methods, but I can not capture that function.
When your application is stopped normally, that is when the JVM is shut down, then you can use a shutdown hook.
The code looks like this:
Runtime.getRuntime().addShutdownHook(new Thread(() ->
System.out.println("Hey, your application was stopped manually ...")));
Note that the above does not apply to abnormal JVM exists, such as when the Java process is killed. A normal exit is when either the window is closed or ctrl+C is used on the terminal. There's no way to register an action on to be executed on an abnormal exit.
I am making an application in Java where I want to always have the data saved to a file with minimal saving operations. In other words, whenever the app is closed or an exception is thrown, it will first attempt to save. The one problem: the POWER BUTTON. When a user holds the power button to a computer, it forces the OS to shut down. Now, how exactly do I make Java detect an incoming shut-down, or will the JVM shut the system first (therefore calling shutdown hooks)?
I summarize here what was mostly already written in the comments.
What normally happens when the user presses the power button for more than 4 seconds, is that the bios will cut power to the mainboard and all peripherals.
There is no way software (OS or user software) can react to this situation.
What may happen is that hard drives would flush any hardware buffer and park the heads in a safe position for transportation but it may as well not happen and the programmer has anyway no way to control that.
What you may react to regular system shutdown using shutdown hooks
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.
Like the title says, I have written a program runs 'in the background', preferably as a Windows service. (It happens to be written in Java, with the service part provided by the tanuki wrapper, if this matters. Also, I'm running Vista, but am assuming that this happens on all versions of Windows with UAC.) I run the service as 'User X'.
I also have a companion GUI program which is typically run from the start menu (unprivileged - i.e. 'asInvoker') - also as 'User X'.
The background program (aka the service) creates files. My main need is for the unelevated GUI program to be able to read, write, and delete these files that are created by the service.
This works without hassle as long as 'User X' is not a member of the Administrators group. (Of course an admin login is required to create the service, but that's okay.)
It also works if I turn off UAC, or if I run the background program not as a service (eg. from a command prompt).
But I just can't get it to work when 'User X' is a member of Administrators, and the background program is running as a service.
The symptoms of this problem are that process explorer shows my service process as running privileged (which I glean from the processes properties' Security tab showing 'BUILTIN\Administrators - Owner'). Also, all files created by the service are owned by 'Administrators'.
If I run my background program unprivileged from a command prompt, then process explorer shows 'BUILTIN\Administrators - Deny' and all files created by the program are owned by 'User X'.
Interesting question. I just looked up some information and cannot seem to find an answer for your question as asked initially, but I have a few alternative suggestions.
First, is it feasible to change your service app so that it creates the files required then it changes the permissions on them to what you want?
Second, does the service itself really have to run as "User X"? If so, why? Is there any way around that restriction? If you can bypass that requirement, then you can just make a normal user for the service to run as.
Third, you said preferably as a service, but not that this is a requirement. Does the environment this is used in allow you to use a scheduled task? The task scheduler itself runs as a system service, and it spawns other processes to do the work of the tasks you set up. And, when setting up a scheduled task, there is an option (a check box if you're using the GUI interface) to run the task with highest privileges or not. If you go this route, you can either have the task run at logon, or you can have it run at system start (in which case, make sure you do NOT have selected "run only if logged on"). This should otherwise be similar to your service setup.
Based on your comment below, I think the third suggestion might still be an option. You could still have status information similar to that of a service by making the program handle this in its own way. Your application could have a socket open for its cross-process communication. The background process could open a ServerSocket on a known port, and it could listen for status requests.
Your client application that your users are using could attempt to connect to this socket. If the socket connects, the process is running, otherwise it is not.
If you wanted only a "running/not running" status, this would be sufficient, and the ServerSocket could accept() a connection and then immediately shutdown and close the resulting Socket; you don't even have to accept or send any information since the initial connection is all you need.
If you want to keep the ability to startup/shutdown the task, you could use this same ServerSocket for that ability. If you aren't using the socket for any other data (only for the running-or-not mentioned above), you could have the background process terminate upon receiving any data at all on the socket, regardless of what it is, and the client (or whatever you use to shut down the background process) need only connect and send a byte instead of connect and immediately disconnect.
For startup, if you want to restrain the background process to one instance, there are a few ways to easily do that. I think you should be able to configure it via the task scheduler to only allow one instance of the task. Even if not, you could have a background process starting up connect to the given port it would otherwise listen on to see if it gets a connection from something else already there, if yes this is a second instance of it so abort. Or, even simpler yet, the creation of the ServerSocket should automatically fail if you are using a static port number, so just let the new ServerSocket(myPort) fail on its own, catch the exception, and abort. So there are three different ways to ensure that your process is acting like a proper service.
To start it up in the first place, you can tell the task scheduler to start it up on user logon, or on system boot as mentioned before. You can also configure the task so that users can initiate it themselves (if for whatever reason it's not already running), in fact, you could even have the client the user's are interacting with check on the status of the process and possibly start it automatically if it's not already started - try making a new process and exec() a command such as "schtasks /run /tn "Your Task Name""
I think that covers all the bases you mentioned, and then some. And all of the above should be pretty simple. If you do decide that this might be the route you'd like to take and if either I've overlooked something or you have other criteria which further restrict you from this, let us know again.
In the end I implemented a work-around using Windows scheduled tasks, similar to what is described above, but instead of implementing my own 'start/stop' interface, I wrote a Windows service that manages my program, run as a task. When the service starts, it starts a task, and when the service is asked to stop, is stops the task. So instead of using a socket for the parent to query if the child is running, I use schtasks /Query and parse the output. To make the task exit if the parent exits, I used an RMI keepalive method on my app that was already there.
Windows scheduled tasks have some undesirable defaults for a service that are modifiable through the task scheduler GUI, but not through schtasks' command-line options - namely ExecutionTimeLimit, DisallowStartIfOnBatteries, StopIfGoingOnBatteries.) But these options can be queried and modified using the '/XML' option to schtasks /Query and /Create. So that's what I did.
I also needed to detect if I'm running on a newer or older version of Windows, because if it's an older version (without UAC) then this will all be unnecessary but more importantly defining the task will not work without supplying a password, because the /NP option to schtasks is not available.
The only weakness (other than being complicated) that I know of with my implementation is due to schtasks' note on the /NP option - "Only local resources are available." This turns out to mean that mapped network drives won't be accessible (and I hope that's all it means.) I have SMB support implemented independently, in Java, in my app where it is needed, so this weakness wasn't the end of the world.
This was a lot of work for what can probably be done with a single Win32 call. Maybe one day I will figure out how to do that.