I want to call a method when I terminating my Java application forcefully. I need to release resource I used in my application.
Please help me.
Thanks
It depends a bit on what you mean by "forcefully", but I expect you want to add a Shutdown hook.
Shutdown hooks are small threads which are called whenever Java attempts to shut down. You can add one using the Runtime API, like so:
Runtime.getRuntime().addShutdownHook(Thread hook)
Of course, if you really force a shutdown (by turning the machine off, or running kill -9 on it,) the operating system will shut down Java without giving it a chance to clean up anything. In that case, you won't be able to do anything about it.
This'll be what you want:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
// release your resource
}
});
You need to use Shutdownhook: Here is example:
Runtime.getRuntime ().addShutdownHook (
new Thread () {
#Override
public void run () {
System.out.println ( "Shutdown hook" );
}
} );
Related
I have a Console-Java game. The score from the game will be saved in a JSON file if Ctrl+C is pressed. The process to save the score in a JSON file works. But I don't know, how to detect Ctrl+C from the console and if this happens, I will save the score (just a method call).
With KeyListener it doesn't work on the console (only with JFrame as far as I know).
I couldn't find a solution to my problem on the internet.
Do I have to do it with Runtime? I have tried it, but it didn't work...
Runtime.getRuntime().addShutdownHook(new Thread()
{
public void run()
{
Test.mainThread.interrupt();
}
});
There are similar questions on Stackoverflow, but not for use on the console Catching Ctrl+C in Java
Adding a shutdown hook is the right way to do it, but Test.mainThread.interrupt(); probably will not work. The JVM is already shutting down. Your mainThread is unlikely to have time to respond to an interrupt; once all shutdown hooks finish, Java terminates.
Just have your shutdown hook explicitly perform whatever actions you need taken:
Runtime.getRuntime().addShutdownHook(new Thread()
{
#Override
public void run()
{
try
{
Test.saveScore();
}
catch (IOException e)
{
System.err.println("Couldn't save score before terminating.");
e.printStackTrace();
}
}
});
We know that CTRL-C closes the application and shuts down the JVM. And since it is a normal shutdown, it runs the shutdown hooks. So creating a shutdown hook is a correct approach:
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
// Do something to save the score
}));
Note that we're passing a Runnable here as the shutdown task. So we can pass an object that has the required functionality:
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
gameScores.save(); // assuming we have a gameScores object in this scope
}));
Your initial attempt by interrupting the thread can be viewed as a variant of this approach. Instead of passing the business object - gameScores - we can pass the thread to interrupt it later. But it's better to operate on the business level.
Does Shutdown Hooks run when a computer shut down? I saw a post about this from a while back, and it is from 2015... so it makes me think that this could have been fixed/changed since then. If not, how should I do this, without causing any issues?
EDIT: I have done some testing myself and found that it does not run on system shut down. Using this:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
//some code here
}
});
I am using this so I could be able to disable some token/key that was generated at the start of the program. If I cannot disable the token at the end of the program, things will get all messed up...
Thanks for any input given!
This question already has answers here:
How to get shutdown hook to execute on a process launched from Eclipse
(7 answers)
Closed 5 years ago.
I have added a shutdown hook via:
Runtime.getRuntime().addShutdownHook(myShutdownHook);
It works fine normally, but not when I click the red stop button in Eclipse. Is there a way to make the shutdown hook be called in Eclipse?
The red stop button forcibly kills the application, i.e. not gracefully, so the JVM doesn't know that the application is exiting, therefore the shutdown hooks are not invoked.
Unfortunately, there is no way (in Windows, at least) to provide a mechanism that ensures that the hook is always invoked. It's just something that may be invoked, but there is no guarantee.
I made a hack by replacing JavaProcess with decorated one:
IProcess p = launch.getProcesses()[0];
launch.addProcess(new JavaProcessDecorator(p));
launch.removeProcess(p);
And decorator is overriding terminate function.
public class JavaProcessDecorator implements IProcess {
private IProcess p;
public JavaProcessDecorator(IProcess p) {
this.p = p;
}
private boolean sigkill = false;
#SuppressWarnings("rawtypes")
#Override public Object getAdapter(Class arg) { return p.getAdapter(arg); }
...
#Override public ILaunch getLaunch() { return p.getLaunch(); }
#Override public IStreamsProxy getStreamsProxy() { return p.getStreamsProxy(); }
#Override public void setAttribute(String s1, String s2) { p.setAttribute(s1, s2); }
#Override public void terminate() throws DebugException {
if(!sigkill) {
try {
IDebugIService cs = DirmiServer.INSTANCE.getRemote("main", IDebugIService.class);
if(cs != null) cs.modelEvent(new TerminateRequest());
} catch (RemoteException e) { }
this.sigkill = true;
} else p.terminate();
}}
At first click on red button, I send a message to application asking for gently termination. If it is not working, second click on red button will kill it.
I know I'm a bit late to the party, but I found this thread seeking for help and so will probably others.
We had the same issue and solved it with an Eclipse plugin (on Linux) which provides additional stop buttons now.
I hope this serves all of you as well as it did help us :)
Red stop button just terminates the application and according to eclipse devs they can't do anything about it see this issue in eclipse bug tracker.
#Pacerier - From the Javadoc: 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.
If you just want to test if the hook is working or not, throw new RuntimeException() from the trigger point. This should call the shutdown hook even from Eclipse.
I was going through shutdown hook feature of java , My analysis was ..shutdownhook allows to register a thread that will be created immediatly but started only when the JVM ends ! So it is some kind of "global jvm finalizer", and you can make useful stuff in this thread (for example shutting down java ressources like an embedded hsqldb server). This works with System.exit(), or with CTRL-C / kill -15 (but not with kill -9 on unix, of course).
Please advise more practical uses and please also if possibe an small example will help to make understanding more clear..!
When a shutdown hook is added to a Runtime instance, it is added to a list of Threads to start upon clean termination of the JVM.
Example: Using shutdown hook to ensure that a java.awt.TrayIcon is removed from the system tray.
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
if (SystemTray.isSupported()) {
SystemTray.getSystemTray().remove(yourTrayIcon);
}
} catch (Exception e) {
// failed to remove
e.printStackTrace();
}
}
});
More can be read in the offical documentation.
I have made a java application and have packed it into an executable jar file. Now a user can start that program from either of the following two ways:
Start if from command prompt by executing the following command on the command prompt:
java -jar "MyJar.jar"
By double clicking on that jar file.
I want that my client would adopt second approach as it is much easier than the first approach. But the problem with second approach is how to stop application before it has finished?
It is a command-line application.
And no command prompt window appears when a user double clicks on the jar file. So in this case, Will Ctrl + c work?
Stopping (exiting) the application should be inside the application. Whether it is command line or GUI based, the application developer should write code to exit it (For eg., in a command line application you might have something like Press 5 to exit, Press Esc to Exit etc) and in an application with a GUI, you will have to write code to exit when the window is closed, or an EXIT button (or others, depending on your application)
Ctrl + C is KILL the application. This is not a Normal exit. For apps with a GUI, the user would typically (in Windows) go to task manager and end the process (similar ways in other operating systems)
But these are abnormal exits - when the user wants to kill the app when, for instance, the application is no longer responding. Normal exits should be provided by the application (and therefore by the programmer - you)
I've had a similar problem. I have some Java programs that are basically long-running daemon processes. It's nice to be able to stop them and bounce (restart) them.
I've used two approaches. Both have advantages and disadvantages. One is to set up a signal handler, by putting a function like this in some class of your program (in mine, it's in the class with the main method).
import sun.misc.Signal;
import sun.misc.SignalHandler;
...
private static boolean stopNow = false;
private static boolean restartNow = false;
...
private static void handleSignals() {
try {
Signal.handle(new Signal("TERM"), new SignalHandler() {
// Signal handler method for CTRL-C and simple kill command.
public void handle(Signal signal) {
MyClass.stopNow = true;
}
});
}
catch (final IllegalArgumentException e) {
logger.warn("No SIGTERM handling in this instance.");
}
try {
Signal.handle(new Signal("INT"), new SignalHandler() {
// Signal handler method for kill -INT command
public void handle(Signal signal) {
MyClass.stopNow = true;
}
});
}
catch (final IllegalArgumentException e) {
logger.debug("No SIGINT handling in this instance.");
}
try {
Signal.handle(new Signal("HUP"), new SignalHandler() {
// Signal handler method for kill -HUP command
public void handle(Signal signal) {
MyClass.restartNow = true;
}
});
}
catch (final IllegalArgumentException e) {
logger.warn("No SIGHUP handling in this instance.");
}
}
This has worked robustly for us in production. You need a genuine Sun JRE for this to work; the one shipped with a typical Linux distro doesn't have the Signal stuff in it. It works OK on Windows too, but you don't get the HUP signal. You do need a shortcut or shellscript to launch this thing.
Also, keep in mind that signal handling is a big fat botch. Don't try to do very much inside your signal handler. You can see that my sample code simply sets static flags. Other parts of my program detect that the flag changed, and shut down. I could have experimented with more complex code inside the signal handler, but I didn't feel like taking on the QA burden.
The other approach is to structure your program as a Servlet. You'll write a class that extends HttpServlet in this case. Override Servlet.init with a method that starts your worker thread. Likewise, Override Servlet.destroy with a method that shuts yourself down.
Then you can use a Java EE container server like Tomcat to manage your starting and stopping.
If your program is a console mode program and it's doing output, Ctrl-C should be able to kill it.
If it's a GUI program, you'll want to give it a button to exit, or at least setting EXIT_ON_CLOSE as the defaultCloseOperation of your main JFrame.
ctrl+alt+suppr -> kill the javaw.exe ? :p
Or you would have to present a user interface with a stop button (see swing etc)
It depends on the User Interface. If its a Swing application then you can setDefaulCloseOperation(JFrame.EXIT_ON_CLOSE) on your main Frame. If its a console app and the user is interacting with it then you ask the user to enter a value that indicates to you that they want to stop the app. If yoy are not interacting with the user at all then ctrl-c will have to work.
Is it a GUI application or commandline.
In first case just handle the window closing event. In second case handle e.g. CTRL + C
that depends on what kind of application is it?
Is it a swing application? If so, then your app should handle when user clicks the 'close' button. There is a behavior for that. JFrame.close()
If it isnt a swing app then ctrl+c will work.
"It is a command-line application" you say.. Well you could do it so that when the user hit a button (say esc) he can write short commands to exit, restart etc..
You can do this with KeyListener. When ESC is hit (say that is the button you want the user to hit), you use Scanner on System.in, and you will do a System.exit(0); if the input is "exit".
I've used socket connection to enable kill of running instance.
//send kill signal to running instance, if any
try {
new Socket("localhost", 4000).getInputStream().read(); //block until its done
} catch (Exception e) { //if no one is listening, we're the only instance
}
//start kill listener for self
new Thread() {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(4000);
serverSocket.accept();
//do cleanup here
serverSocket.close();
} catch (Exception e) {
}
System.exit(0);
}
}.start();
You can use this one: exit()
It's possible to predefine all the action before virtual machine is totally stoppeed thus you can save your data and performa all actions to prevent the data loss.
I'm not sure it's a good way, because I've just started Java study, but it seems working.