...
Java provides two options for program termination: Runtime.exit()
(this which is equivalent to System.exit()
) and Runtime.halt()
.
...
Runtime.exit()
is the typical way of exiting a program. According to the Java API [API 062014], Runtime.exit()
:
terminates the currently running Java virtual machine by initiating its shutdown sequence. This method never returns normally. The argument serves as a status code; by convention, a nonzero status code indicates abnormal termination.
The virtual machine's shutdown sequence consists of two phases. In the first phase all registered shutdown hooks, if any, are started in some unspecified order and allowed to run concurrently until they finish. In the second phase all uninvoked finalizers are run if finalization-on-exit has been enabled. Once this is performed the virtual machine halts.
If this method is invoked after the virtual machine has begun its shutdown sequence, then if shutdown hooks are being run, this method will block indefinitely. If shutdown hooks have already been run and on-exit finalization has been enabled, then this method halts the virtual machine with the given status code if the status is nonzero; otherwise, it blocks indefinitely.
The
System.exit()
method is the conventional and convenient means of invoking this method.
The Runtime.addShutdownHook()
method can be used to customize Runtime.exit()
to perform additional actions at program termination.
This method uses a Thread
, which must be initialized but unstarted. The thread starts when the Java Virtual Machine (JVM) begins to shut down. Because the JVM usually has a fixed time to shut down, these threads should not be long-running and should not attempt user interaction.
...
Runtime.halt()
is similar to Runtime.exit()
but does not run shutdown hooks or finalizers. According to the Java ava API [API 062014], Runtime.halt()
forcibly terminates the currently running Java virtual machine. This method never returns normally.
This method should be used with extreme caution. Unlike the exit method, this method does not cause shutdown hooks to be started and does not run uninvoked finalizers if finalization-on-exit has been enabled. If the shutdown sequence has already been initiated, then this method does not wait for any running shutdown hooks or finalizers to finish their work.
...
This solution explicitly closes the file before exiting.:
Code Block | ||
---|---|---|
| ||
public class CreateFile { public static void main(String[] args) throws FileNotFoundException { final PrintStream out = new PrintStream(new BufferedOutputStream( new FileOutputStream("foo.txt"))); try { out.println("hello"); } finally { try { out.close(); } catch (IOException x) { // handleHandle error } } Runtime.getRuntime().exit(1); } } |
...
This noncompliant code example calls Runtime.halt()
instead of Runtime.exit()
. The Runtime.halt()
method stops the JVM without invoking any shutdown hooks; consequently, the file is not properly written to or closed.
...
When a user forcefully exits a program, for example by pressing the ctrl Ctrl+ cC keys or by using the kill
command, the JVM terminates abruptly. Although this event cannot be captured, the program should nevertheless perform any mandatory cleanup operations before exiting. This noncompliant code example fails to do so.
Code Block | ||
---|---|---|
| ||
public class InterceptExit { public static void main(String[] args) throws FileNotFoundException { InputStream in = null; try { in = new FileInputStream("file"); System.out.println("Regular code block"); // Abrupt exit such as ctrl + c key pressed System.out.println("This never executes"); } finally { if (in != null) { try { in.close(); // thisThis never executes either } catch (IOException x) { // handleHandle error } } } } } |
Compliant Solution (addShutdownHook()
)
Use the addShutdownHook()
method of java.lang.Runtime
to assist with performing clean-up cleanup operations in the event of abrupt termination. The JVM starts the shutdown hook thread when abrupt termination is initiated; the shutdown hook runs concurrently with other JVM threads.
According to the Java API [API 20062014], Class class Runtime
, method addShutdownHook()
,
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. Once the shutdown sequence has begun it can be stopped only by invoking the halt method, which forcibly terminates the virtual machine....
Once the shutdown sequence has begun it is impossible to register a new shutdown hook or de-register a previously registered hook.
Some precautions must be taken because the JVM might be in a sensitive state during shutdown. Shutdown hook threads should
- be Be lightweight and simple.
- be Be thread-safe.
- hold Hold locks when accessing data and release those locks when done.
- avoid Avoid relying on system services, because the services themselves may be shut down (for example, the logger may be shut down from another hook).
To avoid race conditions or deadlock between shutdown actions, it may be better to run a series of shutdown tasks from one thread by using a single shutdown hook [Goetz 2006].
This compliant solution shows the standard method to install a hook.:
Code Block | ||
---|---|---|
| ||
public class Hook { public static void main(String[] args) { try { final InputStream in = new FileInputStream("file"); Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { // Log shutdown and close all resources in.close(); } }); // ... } catch (IOException x) { // handleHandle error } catch (FileNotFoundException x) { // handleHandle error } } } |
The JVM can abort for external reasons, such as an external SIGKILL
signal (POSIX) or the TerminateProcess()
call (Windows), or because of memory corruption caused by native methods. Shutdown hooks may fail to execute as expected in such cases because the JVM cannot guarantee that they will be executed as intended.
...
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
FIO14-J | mediumMedium | likelyLikely | mediumMedium | P12 | L1 |
Related Guidelines
Termination Strategy [REU] | |
CWE-705. Incorrect control flow scoping, Incorrect Control Flow Scoping |
Android Implementation Details
Although most of the code examples are not applicable to the Android platform, the principle is applicable to Android. There are Aprocess on Android can be terminated in a number of ways to terminate a process on Android: android.app.Activity.finish()
, and the related finish... ()
methods, android.app.Activity.moveTaskToBack(boolean flag)
, android.os.Process.killProcess(int pid)
, and System.exit()
.
Bibliography
Section 6.46, "Termination Strategy [REU]" |
...