Call a function before jetty stop - java

In the project I am working on, we need to "save" the work before jetty stopped, on linux this is just easy, because we can call another process, on windows, this is not easy, because we are registering in into Windows service, which means we can either modify the start.jar file to make something before the "stop" function being called, or, well here I need help:
I want, that jetty executes some process before it trigger the stop() function, or even before calling the start.Main class, is this possible?
Thank you

Use shutdown hooks:
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.
That is, a shutdown hook keeps the JVM running until the hook has terminated (returned from the run()-method.
You will have to extend Jetty code with this functionality.

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.

Proper shutdown of JVM when launching from C++

I'm launching JVM from C++ code via JNI. I have a problem that when just quitting my C++ process it seems some shutdown hooks from JVM are not run, and therefore some temp resources are still being around, that in my particular case prevents launching JVM next time I open a C++ process.
I tried jvm->DestroyJavaVM(), but after all my process windows were closed, I still could see the process running. What's the best wait to ensure that the JVM is shut down properly when launched via JNI?
Thanks!
First of all, jvm->DestroyJavaVM() won't return till all non-daemon jvm threads have stopped, it does nothing but waiting for them to stop, so you should stop them in java.
Secondly, System.exit will cause the whole process to be shut down.
So what you really need is check your java code that which thread is not stopped yet, for example the background message loop thread of the ui framework such as gwt or swing.
The easiest way is to call System.exit via JNI.

How to gracefully shutdown a Java application that is terminated as a result of closing the command line from which it was executed?

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.

How do I use swing in a shutdown hook?

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. :)

Cygwin CTRL-C (Signal Interrupts) not working properly - JVM Shutdown Hooks not starting

I'm working on a Java application that utilises shutdown hooks in order to clean up on termination/interruption of the program, but I've noticed that Cygwin's implementation of CTRL-C doesn't seem to trigger the shutdown hooks. On the surface it appears to have interrupted the process, relinquishing control back to the command line, however the process' shutdown hooks are not triggered at all so cleanup does not occur.
In cmd they get caught, but due to various constraints I need to somehow get them working in Cygwin.
Is there any way to fire a SIGINT at a running process through Cygwin at all, or perhaps an alternative to shutdown hooks that I could use to clean up on interruption and termination?
Bash invokes non-cygwin (windows) executables through an intermediate bash process (bash shell -> bash -> java). When you type Ctrl-C, the bash process gets a SIGINT and kills the child java process, so the shutdown hooks are not invoked. Windows processes are not aware of signals like SIGINT, SIGTERM or SIGKILL.
As described in the -Xrs option documentation, the java process registers a console control handler for the CTRL_C_EVENT windows event and that triggers a graceful termination that invokes the shutdown hooks. To get Ctrl-C to work as expected, you'd need to make sure the java process receives it, but right now that's intercepted by bash and not passed forward to the child process.
This issue can be restated as: How can I have Cygwin pass Ctrl-C forward to windows console processes?
Note: The bash behavior described above was verified on version 1.7.25.
This thread perhaps shed some light. Some options
timeout 1d <command>
or
Ctrl-C patch by Howard Chu

Categories

Resources