forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCallsToSystemExit.qhelp
More file actions
71 lines (60 loc) · 3.37 KB
/
CallsToSystemExit.qhelp
File metadata and controls
71 lines (60 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Calling one of the methods <code>System.exit</code>, <code>Runtime.halt</code>, and <code>Runtime.exit</code>
immediately terminates the Java Virtual Machine (JVM),
effectively killing all threads without giving any of them a chance to
perform cleanup actions or recover. As such, it is a dangerous thing to
do: firstly, it can terminate the entire program inadvertently, and
secondly, it can prevent important resources from being released or
program state from being written to disk consistently.</p>
<p>It is sometimes considered acceptable to call <code>System.exit</code>
from a program's <code>main</code> method in order to indicate the overall exit status
of the program. The <code>main</code> method should be the primary place
where exit conditions are handled, as it represents the natural termination point
of the application. Such calls are an exception to this rule.</p>
</overview>
<recommendation>
<p>Instead of calling <code>System.exit</code> from non-main methods, prefer to propagate
errors upward to the <code>main</code> method where they can be handled appropriately.
Consider returning a special value (perhaps <code>null</code>) that users of the current
method check for and recover from appropriately. Alternatively, throw a suitable exception,
which unwinds the stack and allows properly written code to clean up after itself,
while leaving other threads undisturbed. The <code>main</code> method can then catch
these exceptions and decide whether to exit the program and with what exit code.</p>
</recommendation>
<example>
<p>In the following example, problem 1 shows that <code>FileOutput.write</code> tries
to write some data to disk and terminates the JVM if this fails. This
leaves the partially-written file on disk without any cleanup
code running. It would be better to either return <code>false</code> to
indicate the failure, or let the <code>IOException</code> propagate
upwards and be handled by a method that knows how to recover.</p>
<p>Problem 2 is more subtle. In this example, there is just one entry point to
the program (the <code>main</code> method), which constructs an
<code>Action</code> and performs it. <code>Action.run</code> calls
<code>System.exit</code> to indicate successful completion. Instead, the
<code>run</code> method should return a status code or throw an exception
on failure, allowing the <code>main</code> method to decide whether to exit
and with what exit code. Consider how this code might be integrated in an
application server that constructs <code>Action</code> instances and calls
<code>run</code> on them without going through <code>main</code>.
The fact that <code>run</code> terminates the JVM instead of returning its
exit code makes that use-case impossible.</p>
<sample src="CallsToSystemExit.java" />
</example>
<references>
<li>
J. Bloch,
<em>Effective Java (second edition)</em>, p. 232.
Addison-Wesley, 2008.
</li>
<li>Java API Specification:
<a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/System.html#exit(int)">System.exit(int)</a>,
<a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Runtime.html#halt(int)">Runtime.halt(int)</a>,
<a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Runtime.html#exit(int)">Runtime.exit(int)</a>.
</li>
</references>
</qhelp>