This program adds an unusual twist to the usual Hello
world program. What does it print?
public class HelloGoodbye { public static void main(String[] args) { try { System.out.println("Hello world"); System.exit(0); } finally { System.out.println("Goodbye world"); } } }
Solution 39: Hello, Goodbye
The program
contains two println statements: one in a try block and the
other in the corresponding finally block. The TRy block
executes its println and finishes execution prematurely by calling
System.exit. At this point, you might expect control to transfer to the
finally block. If you tried the program, though, you found that it
never can say goodbye: It prints only Hello world. Doesn't this violate
the principle explained in Puzzle 36?
It is true that a finally block is executed when a
try block completes execution whether normally or abruptly. In this
program, however, the try block does not complete execution at all.
The System.exit method halts the execution of
the current thread and all others dead in their tracks. The presence of a
finally clause does not give a thread special permission to continue
executing.
When System.exit is called, the virtual machine
performs two cleanup tasks before shutting down. First, it executes all shutdown hooks that have been registered with
Runtime.addShutdownHook. This is useful to release resources external
to the VM. Use shutdown hooks for behavior that must
occur before the VM exits. The following version of the program
demonstrates this technique, printing both Hello world and Goodbye
world, as expected:
public class HelloGoodbye { public static void main(String[] args) { System.out.println("Hello world"); Runtime.getRuntime().addShutdownHook( new Thread() { public void run() { System.out.println("Goodbye world"); } }); System.exit(0); } }
The second cleanup task performed by the VM when
System.exit is called concerns finalizers. If either
System.runFinalizersOnExit or its evil twin
Runtime.runFinalizersOnExit has been called, the VM runs the finalizers
on all objects that have not yet been finalized. These methods were deprecated a
long time ago and with good reason. Never call
System.runFinalizersOnExit or Runtime.runFinalizersOnExit for
any reason: They are among the most dangerous methods in the Java
libraries [ThreadStop]. Calling these methods can result in finalizers being run on
live objects while other threads are concurrently manipulating them, resulting
in erratic behavior or deadlock.
In summary, System.exit stops all program threads
immediately; it does not cause finally blocks to execute, but it does
run shutdown hooks before halting the VM. Use shutdown hooks to terminate
external resources when the VM shuts down. It is possible to halt the VM without
executing shutdown hooks by calling System.halt, but this method is
rarely used.
No comments:
Post a Comment
Your comments are welcome!