Queries regarding Shutdown hook - java

If i have gotten it correctly each java process is associated with a separate instance of JVM and each instance of JVM is provided with a Heap memory by the OS which is also recollected by the OS on JVM termination. So on termination even if there were some memory leaks all the memory will be reclaimed by the OS(Please correct if I have mistaken).
In case point number 1 is true why do we have to use shutdown hooks. After googling everything mainly suggests to free all the resources and graceful shutdown. Even if it does not gracefully shutdown all the memory and resources would be freed?
I wrote a simple shutdown hook. In my main thread I am running an infinite loop and then terminating the process using terminate button in Eclipse. But the shutdown hook thread is not running.
Does terminating process in eclipse call Runtime.getRuntime().halt(status) because AFAIK that terminated JVM abruptly and not execute shutdown hook?
Lastly if I have my main code something like below -
public static void main(String args[]){
Runtime.getRuntime().addShutdownHook(new Thread(new ShutDownHook()));
System.out.println("Shutdown hook registered");
System.out.println("Before calling exit");
System.exit(0);
System.out.println("After exit");
}
why is After exit not printed? When shutdown hook is in execution main thread must continue further execution and print After exit?

1) You are correct.
2) The Java process' memory will be reclaimed, but you might want to do other cleanup, like delete some temp files.
3) Let's go to the javadoc of Runtime#addShutdownHook(Thread)
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.
You would have to look into Eclipse's source code, but it would seem like Eclipse terminates the process rather than sending a System.exit(..) or a sending a user interrupt. This probably goes over the JVM which therefore doesn't execute the shutdown hooks.
4) The shutdown hooks you add with Runtime#addShutdownHook(Thread) are added to a static IdentityHashMap in the ApplicationShutdownHooks. This class registers its own shutdown hook with the Shutdown class in a static initializer block shown below
static {
try {
Shutdown.add(1 /* shutdown hook invocation order */,
false /* not registered if shutdown in progress */,
new Runnable() {
public void run() {
runHooks();
}
}
);
hooks = new IdentityHashMap<>();
} catch (IllegalStateException e) {
// application shutdown hooks cannot be added if
// shutdown is in progress.
hooks = null;
}
}
The runHooks() method is
static void runHooks() {
Collection<Thread> threads;
synchronized(ApplicationShutdownHooks.class) {
threads = hooks.keySet();
hooks = null;
}
for (Thread hook : threads) {
hook.start();
}
for (Thread hook : threads) {
try {
hook.join();
} catch (InterruptedException x) { }
}
}
So the current thread joins all the other ones.
When
System.exit(0);
gets called, somewhere down the line Shutdown.sequence() gets called which invokes Shutdown.hooks() implemented as
private static void runHooks() {
for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {
try {
Runnable hook;
synchronized (lock) {
// acquire the lock to make sure the hook registered during
// shutdown is visible here.
currentRunningHook = i;
hook = hooks[i];
}
if (hook != null) hook.run();
} catch(Throwable t) {
if (t instanceof ThreadDeath) {
ThreadDeath td = (ThreadDeath)t;
throw td;
}
}
}
}
One of the Runnable objects in hooks is what I described above. It doesn't spawn a new Thread, it does it concurrently with run().
Once Shutdown.sequence() is done, the system really exits, so the final System.out.println() doesn't execute.

Related

Block Java application from exiting until ThreadPool is empty

I've got an ExecutorService sitting inside a singleton class which receives tasks from many different classes. On application shutdown, I need to wait for the pool to be empty before I allow the application to exit.
private static NotificationService instance = null;
private ExecutorService executorService = Executors.newFixedThreadPool(25);
public static synchronized NotificationService getInstance() {
if (instance == null) {
instance = new NotificationService(true);
}
return instance;
}
While using this NotificationService, it frequently happens that I restart the application and the executorService hasn't finished processing all the notifications.
For Testing, I can manually shutdown the executorService and wait until all tasks are completed.
public static boolean canExit() throws InterruptedException {
NotificationService service = getInstance();
service.executorService.shutdown();
service.executorService.awaitTermination(30, TimeUnit.SECONDS);
return service.executorService.isTerminated();
}
Is it reliable and safe to override the finalize method and wait there until the pool is empty? From what I've read, finalize is not always called, especially not when using a singleton class.
#Override
protected void finalize() throws Throwable {
while (!canExit()){
Thread.sleep(100);
}
super.finalize();
}
This code is included in a library that will be included in another application, so there's no main method where I can wait until the pool is empty, unless I force the person using it to do so which is not great.
What is the correct way to stall the application (for a reasonable amount of time) from terminating until the pool is empty?
You can use addShutdownHook to catch the process termination event and wait for the pool there.
example:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
NotificationService service = getInstance();
service.executorService.shutdown();
service.executorService.awaitTermination(30, TimeUnit.SECONDS);
}
});
Answered here: Java Finalize method call when close the application
Finalizers do not run on exit by default and the functionality to do this is deprecated.
One common advice is to use the Runtime.addShutdownHook but be aware of the following line of documentation:
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 all honesty the best way to ensure everything gets properly cleaned up is to have your own application lifecycle which you can end before you even ask the VM to exit.
Don't use blocking shutdown hooks or anything similar in a library. You never know how the library is meant to be used. So it should always be up to the code that is using your library to take sensible actions on shut down.
Of course, you have to provide the necessary API for that, e.g. by adding lifecycle-methods to your class:
public class NotificationService {
...
public void start() {
...
}
/**
* Stops this notification service and waits until
* all notifications have been processed, or a timeout occurs.
* #return the list of unprocessed notification (in case of a timeout),
or an empty list.
*/
public List<Notification> stop(long timeout, TimeUnit unit) {
service.shutdown();
if (!service.awaitTermination(timeout, unit)) {
List<Runnable> tasks = service.shutdownNow();
return extractNotification(tasks);
}
return Collections.emptyList();
}
private List<Notification> extractNotification(List<Runnable> tasks) {
...
}
}
Then, the application code can take the required actions to handle your service, e.g.:
public static void main(String[] args) {
NotificationService service = new NotificationService(...);
service.start();
try {
// use service here
} finally {
List<Notification> pending = service.stop(30, TimeUnit.SECONDS);
if (!pending.isEmpty()) {
// timeout occured => handle pending notifications
}
}
}
Btw.: Avoid using singletons, if feasible.

Kill Java Thread for testing purposes

I'm currently testing a transaction system with ACID semantics implemented in Java. The system has callback handlers that allow to perform arbitrary debug actions during a transaction, e.g. to throw an exception that simulates an error.
However, in practice what can happen is the death of a thread (e.g. by OutOfMemoryError) or the death of the entire JVM (sigsev or OS process kill). I can see that it's impossible to simulate the unexpected shutdown of the JVM process in a JUnit test (because JUnit runs in the same JVM). But what about killing a thread? I know about Thread#stop(), but it's deprecated and moreover throws a ThreadDeathError in the thread. What I would like to simulate is the instantaneous "death" of a thread that prevents even catch(Throwable t) clauses from firing. Can this be done in Java, without killing the JUnit test runner alongside it?
Again, this is not for production use, it's strictly testing only.
the instantaneous "death" of a thread that prevents even catch(Throwable t) clauses from firing. Can this be done in Java?
No. It's impossible.
JVM uses OS threads and thus relies on the underlying OS scheduler. So in JVM level, JVM can't preempt a java thread. A java thread must volunteer to be suspended. (It's common case, but still platform- and JVM-specific)
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
int i = 0;
i++;
}
}
});
t1.start();
Thread.sleep(1000);
t1.stop();
Thread.sleep(1000);
System.out.println(t1.isAlive());
}
In the above code, stop() worked. But you might wonder why an infinite loop without wait()/sleep() looks like "doesn't volunteer to be suspended"?
stop() raise an asynchronous exception in t1. t1 thread can detect the async exception by polling.
From Java Virtual Machine Specification:
The stop methods may be invoked by one thread to affect another thread or all the threads in a specified thread group. They are asynchronous because they may occur at any point in the execution of the other thread or threads. An internal error is considered asynchronous
A simple implementation might poll for asynchronous exceptions at the point of each control transfer instruction.
Which means, in the compiled code, at the end of the while-loop before jump, there's an instruction to poll the exception. If the exception exists, the t1 thread jump to exception handler and stop by it self.
So if I make the thread ignore all exceptions, and if the thread doesn't stop by it self, it's impossible to kill a java thread.
Here's an example where stop() doesn't work:
public static void main(String [] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
while (true) {
int i = 0;
i++;
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
});
t1.start();
Thread.sleep(1000);
t1.stop();
Thread.sleep(1000);
System.out.println(t1.isAlive());
}

java create un-cooperative thread for testing

I've been bit a few times by a java process that wouldn't cooperate and exit cleanly (it would be buried in some low-level libraries out of my control). I am now testing a sort of watchdog that implements a hard stop for the process at some pre-established time, ScheduledStop. That watchdog is a singleton class that runs an independent thread that will kill the whole process if the scheduled stop time arrives. Normally, all threads should return nicely before that hard-stop time and the program exits gracefully. If necessary however, the process kills itself, file locks are released etc. All of this runs on Linux.
I seem to remember that even System.exit(0) is not fool-proof (I think if some shutdown hooks are getting stuck, the process may stay alive), so I have concocted something along the line of:
int pid = MyUtil.getPID();
Runtime.getRuntime().exec(new String[]{"kill", "-9", String.valueOf(pid)});
Now, I'd like to test it with some really un-cooperative threads, and possibly some shutdown hooks that, on purpose for the test, are not doing well.
The itinial NastyThread below is not all that nasty... It ignores InterruptionException, but doesn't prevent System.exit(0). How can I put my VM into a state that even exit() doesn't terminate?
Another question is, although the watchdog thread is in theory independent, what are the conditions where other threads would completely preempt it, thus foiling the scheduled stop?
If necessary, I could launch a separate process (e.g. a simple perl script) that kills the parent (the java process) at some specified time.
/**
* A Runnable that runs forever and ignores InterruptedException.
*/
private static class NastyThread implements Runnable {
#Override
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("Received and ignoring "+e);
System.out.flush();
}
System.out.println(ScheduledStop.getInstance().toString());
}
}
}
You can set a SecurityManager to ignore or throw an Error when System.exit() is called.
BTW
while(true) Thread.yield();
or
for(;;);
will ignore interrupts as well.
Ok, I added a SecurityManager as suggested by #Lawrey. Somehow the application can still happily System.exit(0).
But then, I added a shutdown hook that just launches one more nasty thread! That does the trick, and now my ScheduledStop class can be tested (and works). Here is the shutdown hook:
Runtime.getRuntime().addShutdownHook(new Thread(
new NastyThread("nasty-1 (shutdown-hook)")
));
Here is the output of the test:
gp> ~$ java -cp "$CLASSPATH" com.somepackage.ScheduledStop
nasty-0: Stop scheduled at 20130916-111611-PDT (in PT4.488S)
nasty-0: Stop scheduled at 20130916-111611-PDT (in PT3.939S)
nasty-0: Stop scheduled at 20130916-111611-PDT (in PT3.437S)
main would like to exit(0).
nasty-0: Stop scheduled at 20130916-111611-PDT (in PT2.936S)
nasty-1 (shutdown-hook): Stop scheduled at 20130916-111611-PDT (in PT2.487S)
nasty-0: Stop scheduled at 20130916-111611-PDT (in PT2.434S)
nasty-1 (shutdown-hook): Stop scheduled at 20130916-111611-PDT (in PT1.985S)
nasty-0: Stop scheduled at 20130916-111611-PDT (in PT1.932S)
nasty-1 (shutdown-hook): Stop scheduled at 20130916-111611-PDT (in PT1.484S)
nasty-0: Stop scheduled at 20130916-111611-PDT (in PT1.431S)
nasty-1 (shutdown-hook): Stop scheduled at 20130916-111611-PDT (in PT0.981S)
nasty-0: Stop scheduled at 20130916-111611-PDT (in PT0.928S)
nasty-1 (shutdown-hook): Stop scheduled at 20130916-111611-PDT (in PT0.479S)
nasty-0: Stop scheduled at 20130916-111611-PDT (in PT0.426S)
Hard stop (kill -9 self=6967).
zsh: killed java -cp "$CLASSPATH" com.somepackage.ScheduledStop
FWIW, here is the whole "test" code (not a real test, just taking ScheduledStop for a little drive around the block):
/*----------------------------------
* all the code below is for testing
*/
/**
* A Runnable that runs forever and ignores InterruptedException.
*/
private static class NastyThread implements Runnable {
private final String name;
public NastyThread(String name) {
super();
this.name = name;
}
#Override
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println(name+": received and ignoring "+e);
System.out.flush();
}
System.out.println(name+": "+ScheduledStop.getInstance().toString());
}
}
}
#SuppressWarnings("serial")
private static class ExitTrappedException extends SecurityException { }
private static void forbidSystemExitCall() {
final SecurityManager securityManager = new SecurityManager() {
public void checkPermission(Permission permission ) {
if ("exitVM".equals(permission.getName())) {
throw new ExitTrappedException() ;
}
}
};
try {
System.setSecurityManager(securityManager);
} catch (Exception e) {
System.err.println("got: "+e);
}
}
#SuppressWarnings("unused")
private static void enableSystemExitCall() {
System.setSecurityManager( null ) ;
}
/**
* Spawn an un-cooperative thread, then kill itself after a few seconds.
*/
public static void main(String[] args) throws IOException {
final File lockFile = new File("testStop.lock");
final Period runFor = Period.seconds(5);
try (HplFileLock lock = FileUtil.getFileLockOrExit(lockFile, 0)) {
ScheduledStop.getInstance().runFor(runFor);
} catch (Exception e) {
System.err.println("Exception: " + e);
System.err.flush();
System.exit(-1);
}
// disallow System.exit()
forbidSystemExitCall();
// launch a pesky thread that ignores interruption
Runnable r = new NastyThread("nasty-0");
new Thread(r).start();
// further, install a shutdown hook that just launches one more NastyThread!
Runtime.getRuntime().addShutdownHook(new Thread(new NastyThread("nasty-1 (shutdown-hook)")));
// now wait 2 seconds and try to exit
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main would like to exit(0).");
System.out.flush();
System.exit(0);
}

Handling Shutdown Event

Hi I have an Standalone application in which when an user logs in a abc.lck file gets created when the application is closed it gets deleted.I have used addshutdownhook() to delete the file when power supply is interrupted that is switching off the power supply when my application is running.My problem is the file is not getting deleted when I manually shutdown the system i.e by start-->shutdown and I should prompt the user with a message to save the changes using cofirm dailog box like in MS Word.Can some one help me
Thanking u
Chaithu
The general contract of addShutdown hook is
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.
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.
Hence during shutdown, the Windows machine may call TerminateProcess and hence your shutdown hook might not be invoked.
Use deleteOnExit method instead of adding shutdownhook. However, take a look at this sample,
class Shutdown {
private Thread thread = null;
protected boolean flag=false;
public Shutdown() {
thread = new Thread("Sample thread") {
public void run() {
while (!flag) {
System.out.println("Sample thread");
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException ie) {
break;
}
}
System.out.println("[Sample thread] Stopped");
}
};
thread.start();
}
public void stopThread() {
flag=true;
}
}
class ShutdownThread extends Thread {
private Shutdown shutdown = null;
public ShutdownThread(Shutdown shutdown) {
super();
this.shutdown = shutdown;
}
public void run() {
System.out.println("Shutdown thread");
shutdown.stopThread();
System.out.println("Shutdown completed");
}
}
public class Main {
public static void main(String [] args) {
Shutdown shutdown = new Shutdown();
try {
Runtime.getRuntime().addShutdownHook(new ShutdownThread(shutdown));
System.out.println("[Main thread] Shutdown hook added");
} catch (Throwable t) {
System.out.println("[Main thread] Could not add Shutdown hook");
}
try {
Thread.currentThread().sleep(10000);
} catch (InterruptedException ie) {}
System.exit(0);
}
}

Get notification on a Java process termination

There is a console Java application which is supposed to run until it is stopped by Ctrl+C or closing the console window. How that application can be programmed to execute a clean up code before exit?
You could use a Shutdown Hook.
Basically you need to create a Thread which will perform your shutdown actions, and then add it as a shutdown hook. For example:
class ShutdownHook extends Thread
{
public void run()
{
// perform shutdown actions
}
}
// Then, somewhere in your code
Runtime.getRuntime().addShutdownHook(new ShutdownHook())
A Shutdown hook is the way to go, but be aware that there is no guarantee that the code is actually executed. JVM crashes, power failures, or a simple "kill -9" on your JVM can prevent the code from cleaning up. Therefore you must ensure that your program stays in a consistent state even if it has been aborted abruptly.
Personally, I simply use a database for all state-storage. Its transactions model makes sure that the persistent storage is in a sane state no matter what happens. They spend years making that code fool-proof, so why should I waste my time on problems already solved.
Program to delete temp file bat.bat when program is exited:
public class Backup {
public static void createBackup(String s)
{
try{
String fileName ="C:\\bat"+ ".bat";
FileWriter writer=new FileWriter(fileName);
String batquery="cd C:\\Program Files\\MySQL\\MySQL Server 5.0\\bin"
+ "\nmysqldump -uroot -proot bankdb > \""+s+".sql\""
+"\nexit";
writer.append(batquery);
writer.close();
}
catch(Exception e){e.getMessage();}
try{
Process p =Runtime.getRuntime().exec("cmd /c start C:\\bat.bat");
}
catch(Exception e){e.getMessage();}
ShutDownHook sdh=new ShutDownHook();
Runtime.getRuntime().addShutdownHook(sdh);
}
}
class ShutDownHook extends Thread
{
public void run()
{
try
{
File f=new File("c:/bat.bat");
f.delete();
}
catch(Exception e){e.getMessage();}
}
}
The code written inside a Threads run() method will execute when the runtime object terminates...
class ShutdownHookclass extends Thread {
public void run() {
// perform shutdown actions
}
}
//could be written anywhere in your code
Runtime.getRuntime().addShutdownHook(new ShutdownHookclass())

Categories