Table of Contents
When a program violates the semantic constraints of the Java programming language, the Java Virtual Machine signals this error to the program as anexception.
An example of such a violation is an attempt to index outside the bounds of an array. Some programming languages and their implementations react to such errors by peremptorily terminating the program; other programming languages allow an implementation to react in an arbitrary or unpredictable way. Neither of these approaches is compatible with the design goals of the Java SE platform: to provide portability and robustness.
Instead, the Java programming language specifies that an exception will be thrown when semantic constraints are violated and will cause a non-local transfer of control from the point where the exception occurred to a point that can be specified by the programmer.
An exception is said to bethrown from the point where it occurred and is said to becaught at the point to which control is transferred.
Programs can also throw exceptions explicitly, usingthrow
statements (§14.18).
Explicit use ofthrow
statements provides an alternative to the old-fashioned style of handling error conditions by returning funny values, such as the integer value-1
where a negative value would not normally be expected. Experience shows that too often such funny values are ignored or not checked for by callers, leading to programs that are not robust, exhibit undesirable behavior, or both.
Every exception is represented by an instance of the classThrowable
or one of its subclasses (§11.1). Such an object can be used to carry information from the point at which an exception occurs to the handler that catches it. Handlers are established bycatch
clauses oftry
statements (§14.20).
During the process of throwing an exception, the Java Virtual Machine abruptly completes, one by one, any expressions, statements, method and constructor invocations, initializers, and field initialization expressions that have begun but not completed execution in the current thread. This process continues until a handler is found that indicates that it handles that particular exception by naming the class of the exception or a superclass of the class of the exception (§11.2). If no such handler is found, then the exception may be handled by one of a hierarchy of uncaught exception handlers (§11.3) - thus every effort is made to avoid letting an exception go unhandled.
The exception mechanism of the Java SE platform is integrated with its synchronization model (§17.1), so that monitors are unlocked assynchronized
statements (§14.19) and invocations ofsynchronized
methods (§8.4.3.6,§15.12) complete abruptly.
An exception is represented by an instance of the classThrowable
(a direct subclass ofObject
) or one of its subclasses.
Throwable
and all its subclasses are, collectively, theexception classes.
The classesException
andError
are direct subclasses ofThrowable
:
Exception
is the superclass of all the exceptions from which ordinary programs may wish to recover.
The classRuntimeException
is a direct subclass ofException
.RuntimeException
is the superclass of all the exceptions which may be thrown for many reasons during expression evaluation, but from which recovery may still be possible.
RuntimeException
and all its subclasses are, collectively, therun-time exception classes.
Error
is the superclass of all the exceptions from which ordinary programs are not ordinarily expected to recover.
Error
and all its subclasses are, collectively, theerror classes.
Theunchecked exception classes are the run-time exception classes and the error classes.
Thechecked exception classes are all exception classes other than the unchecked exception classes. That is, the checked exception classes areThrowable
and all its subclasses other thanRuntimeException
and its subclasses andError
and its subclasses.
Programs can use the pre-existing exception classes of the Java SE platform API inthrow
statements, or define additional exception classes as subclasses ofThrowable
or of any of its subclasses, as appropriate. To take advantage of compile-time checking for exception handlers (§11.2), it is typical to define most new exception classes as checked exception classes, that is, as subclasses ofException
that are not subclasses ofRuntimeException
.
The classError
is a separate subclass ofThrowable
, distinct fromException
in the class hierarchy, to allow programs to use the idiom "} catch (Exception e) {
" (§11.2.3) to catch all exceptions from which recovery may be possible without catching errors from which recovery is typically not possible.
Note that a subclass ofThrowable
cannot be generic (§8.1.2).
An exception is thrown for one of three reasons:
Athrow
statement (§14.18) was executed.
An abnormal execution condition was synchronously detected by the Java Virtual Machine, namely:
evaluation of an expression violates the normal semantics of the Java programming language (§15.6), such as an integer divide by zero.
an error occurs while loading, linking, or initializing part of the program (§12.2,§12.3,§12.4); in this case, an instance of a subclass ofLinkageError
is thrown.
an internal error or resource limitation prevents the Java Virtual Machine from implementing the semantics of the Java programming language; in this case, an instance of a subclass ofVirtualMachineError
is thrown.
These exceptions are not thrown at an arbitrary point in the program, but rather at a point where they are specified as a possible result of an expression evaluation or statement execution.
An asynchronous exception occurred (§11.1.3).
Most exceptions occur synchronously as a result of an action by the thread in which they occur, and at a point in the program that is specified to possibly result in such an exception. Anasynchronous exception is, by contrast, an exception that can potentially occur at any point in the execution of a program.
Asynchronous exceptions occur only as a result of:
An invocation of the (deprecated)stop
method of classThread
orThreadGroup
.
The (deprecated)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 or resource limitation in the Java Virtual Machine that prevents it from implementing the semantics of the Java programming language. In this case, the asynchronous exception that is thrown is an instance of a subclass ofVirtualMachineError
.
Note thatStackOverflowError
, a subclass ofVirtualMachineError
, may be thrown synchronously by method invocation (§15.12.4.5) as well as asynchronously due tonative
method execution or Java Virtual Machine resource limitations. Similarly,OutOfMemoryError
, another subclass ofVirtualMachineError
, may be thrown synchronously during class instance creation (§15.9.4,§12.5), array creation (§15.10.2,§10.6), class initialization (§12.4.2), and boxing conversion (§5.1.7), as well as asynchronously.
The Java SE platform permits a small but bounded amount of execution to occur before an asynchronous exception is thrown.
Asynchronous exceptions are rare, but proper understanding of their semantics is necessary if high-quality machine code is to be generated.
The delay noted above is permitted to allow optimized code to detect and throw these exceptions at points where it is practical to handle them while obeying the semantics of the Java programming language. A simple implementation might poll for asynchronous exceptions at the point of each control transfer instruction. Since a program has a finite size, this provides a bound on the total delay in detecting an asynchronous exception. Since no asynchronous exception will occur between control transfers, the code generator has some flexibility to reorder computation between control transfers for greater performance. The paperPolling Efficiently on Stock Hardware by Marc Feeley,Proc. 1993 Conference on Functional Programming and Computer Architecture, Copenhagen, Denmark, pp. 179-187, is recommended as further reading.
The Java programming language requires that a program contains handlers forchecked exceptions which can result from execution of a method or constructor (§8.4.6,§8.8.5). This compile-time checking for the presence of exception handlers is designed to reduce the number of exceptions which are not properly handled. For each checked exception which is a possible result, thethrows
clause for the method or constructor must mention the class of that exception or one of the superclasses of the class of that exception (§11.2.3).
The checked exception classes (§11.1.1) named in thethrows
clause are part of the contract between the implementor and user of the method or constructor. Thethrows
clause of an overriding method may not specify that this method will result in throwing any checked exception which the overridden method is not permitted, by itsthrows
clause, to throw (§8.4.8.3). When interfaces are involved, more than one method declaration may be overridden by a single overriding declaration. In this case, the overriding declaration must have athrows
clause that is compatible with all the overridden declarations (§9.4.1).
The unchecked exception classes (§11.1.1) are exempted from compile-time checking.
Error classes are exempted because they can occur at many points in the program and recovery from them is difficult or impossible. A program declaring such exceptions would be cluttered, pointlessly. Sophisticated programs may yet wish to catch and attempt to recover from some of these conditions.
Run-time exception classes are exempted because, in the judgment of the designers of the Java programming language, having to declare such exceptions would not aid significantly in establishing the correctness of programs. Many of the operations and constructs of the Java programming language can result in exceptions at run time. The information available to a Java compiler, and the level of analysis a compiler performs, are usually not sufficient to establish that such run-time exceptions cannot occur, even though this may be obvious to the programmer. Requiring such exception classes to be declared would simply be an irritation to programmers.
For example, certain code might implement a circular data structure that, by construction, can never involve null references; the programmer can then be certain that aNullPointerException
cannot occur, but it would be difficult for a Java compiler to prove it. The theorem-proving technology that is needed to establish such global properties of data structures is beyond the scope of this specification.
We say that a statement or expressioncan throw an exception classE if, according to the rules in§11.2.1 and§11.2.2, the execution of the statement or expression can result in an exception of classE being thrown.
We say that acatch
clausecan catch its catchable exception class(es):
The catchable exception class of a uni-catch
clause is the declared type of its exception parameter (§14.20).
The catchable exception classes of a multi-catch
clause are the alternatives in the union that denotes the type of its exception parameter.
A class instance creation expression (§15.9) can throw an exception classE iff either:
The expression is a qualified class instance creation expression and the qualifying expression can throwE; or
E is one of the exception types of the invocation type of the chosen constructor (§15.12.2.6); or
The class instance creation expression includes aClassBody, and some instance initializer or instance variable initializer in theClassBody can throwE.
A method invocation expression (§15.12) can throw an exception classE iff either:
The method invocation expression is of the formPrimary.
[TypeArguments]Identifier and thePrimary expression can throwE; or
E is one of the exception types of the invocation type of the chosen method (§15.12.2.6).
A lambda expression (§15.27) can throw no exception classes.
For every other kind of expression, the expression can throw an exception classE iff one of its immediate subexpressions can throwE.
Note that a method reference expression (§15.13) of the formPrimary::
[TypeArguments] Identifier can throw an exception class if thePrimary subexpression can throw an exception class. In contrast, a lambda expression can throw nothing, and has no immediate subexpressions on which to perform exception analysis. It is thebody of a lambda expression, containing expressions and statements, that can throw exception classes.
Athrow
statement (§14.18) whose thrown expression has static typeE and is not a final or effectively final exception parameter can throwE or any exception class that the thrown expression can throw.
For example, the statementthrow new java.io.FileNotFoundException();
can throwjava.io.FileNotFoundException
only. Formally, it is not the case that it "can throw" a subclass or superclass ofjava.io.FileNotFoundException
.
Athrow
statement whose thrown expression is a final or effectively final exception parameter of acatch
clauseC can throw an exception classE iff:
E is an exception class that thetry
block of thetry
statement which declaresC can throw; and
E is assignment compatible with any ofC's catchable exception classes; and
E is not assignment compatible with any of the catchable exception classes of thecatch
clauses declared to the left ofC in the sametry
statement.
Atry
statement (§14.20) can throw an exception classE iff either:
Thetry
block can throwE, or an expression used to initialize a resource (in atry
-with-resources statement) can throwE, or the automatic invocation of theclose()
method of a resource (in atry
-with-resources statement) can throwE, andE is not assignment compatible with any catchable exception class of anycatch
clause of thetry
statement, and either nofinally
block is present or thefinally
block can complete normally; or
Somecatch
block of thetry
statement can throwE and either nofinally
block is present or thefinally
block can complete normally; or
An explicit constructor invocation statement (§8.8.7.1) can throw an exception classE iff either:
Some expression of the constructor invocation's parameter list can throwE; or
E is determined to be an exception class of thethrows
clause of the constructor that is invoked (§15.12.2.6).
Any other statementS can throw an exception classE iff an expression or statement immediately contained inS can throwE.
It is a compile-time error if a method or constructor bodycan throw some exception classE whenE is a checked exception class andE is not a subclass of some class declared in thethrows
clause of the method or constructor.
It is a compile-time error if a lambda bodycan throw some exception classE whenE is a checked exception class andE is not a subclass of some class declared in thethrows
clause of the function type targeted by the lambda expression.
It is a compile-time error if a class variable initializer (§8.3.2) or static initializer (§8.7) of a named class or interfacecan throw a checked exception class.
It is a compile-time error if an instance variable initializer (§8.3.2) or instance initializer (§8.6) of a named classcan throw a checked exception class, unless the named class has at least one explicitly declared constructor and the exception class or one of its superclasses is explicitly declared in thethrows
clause of each constructor.
Note that no compile-time error is due if an instance variable initializer or instance initializer of an anonymous class (§15.9.5) can throw an exception class. In a named class, it is the responsibility of the programmer to propagate information about which exception classes can be thrown by initializers, by declaring a suitablethrows
clause on any explicit constructor declaration. This relationship between the checked exception classes thrown by a class's initializers and the checked exception classes declared by a class's constructors is assured for an anonymous class declaration, because no explicit constructor declarations are possible and a Java compiler always generates a constructor with a suitablethrows
clause for the anonymous class declaration based on the checked exception classes that its initializers can throw.
It is a compile-time error if acatch
clausecan catch checked exception classE1 and it is not the case that thetry
block corresponding to thecatch
clausecan throw a checked exception class that is a subclass or superclass ofE1, unlessE1 isException
or a superclass ofException
.
It is a compile-time error if acatch
clausecan catch an exception classE1 and a precedingcatch
clause of the immediately enclosingtry
statementcan catchE1 or a superclass ofE1.
A Java compiler is encouraged to issue a warning if acatch
clause can catch checked exception classE1 and thetry
block corresponding to thecatch
clause can throw checked exception classE2, whereE2<:
E1, and a precedingcatch
clause of the immediately enclosingtry
statement can catch checked exception classE3, whereE2<:
E3<:
E1.
Example 11.2.3-1. Catching Checked Exceptions
import java.io.*;class StaticallyThrownExceptionsIncludeSubtypes { public static void main(String[] args) { try { throw new FileNotFoundException(); } catch (IOException ioe) { // "catch IOException" catches IOException // and any subtype. } try { throw new FileNotFoundException(); // Statement "can throw" FileNotFoundException. // It is not the case that statement "can throw" // a subtype or supertype of FileNotFoundException. } catch (FileNotFoundException fnfe) { // ... Handle exception ... } catch (IOException ioe) { // Legal, but compilers are encouraged to give // warnings as of Java SE 7, because all subtypes of // IOException that the try block "can throw" have // already been caught by the prior catch clause. } try { m(); // m's declaration says "throws IOException", so // m "can throw" IOException. It is not the case // that m "can throw" a subtype or supertype of // IOException (e.g. Exception). } catch (FileNotFoundException fnfe) { // Legal, because the dynamic type of the exception // might be FileNotFoundException. } catch (IOException ioe) { // Legal, because the dynamic type of the exception // might be a different subtype of IOException. } catch (Throwable t) { // Can always catch Throwable. } } static void m() throws IOException { throw new FileNotFoundException(); }}
By the rules above, each alternative in a multi-catch
clause (§14.20) must be able to catch some exception class thrown by thetry
block and uncaught by previouscatch
clauses. For example, the secondcatch
clause below would cause a compile-time error because exception analysis determines thatSubclassOfFoo
is already caught by the firstcatch
clause:
try { ... }catch (Foo f) { ... }catch (Bar | SubclassOfFoo e) { ... }
When an exception is thrown (§14.18), control is transferred from the code that caused the exception to the nearest dynamically enclosingcatch
clause, if any, of atry
statement (§14.20) that can handle the exception.
A statement or expression isdynamically enclosed by acatch
clause if it appears within thetry
block of thetry
statement of which thecatch
clause is a part, or if the caller of the statement or expression is dynamically enclosed by thecatch
clause.
The caller of a statement or expression depends on where it occurs:
If within a method, then the caller is the method invocation expression (§15.12) that was executed to cause the method to be invoked.
If within a constructor or an instance initializer or the initializer for an instance variable, then the caller is the class instance creation expression (§15.9) or the method invocation ofnewInstance
that was executed to cause an object to be created.
If within a static initializer or an initializer for astatic
variable, then the caller is the expression that used the class or interface so as to cause it to be initialized (§12.4).
Whether a particularcatch
clausecan handle an exception is determined by comparing the class of the object that was thrown to the catchable exception classes of thecatch
clause. Thecatch
clause can handle the exception if one of its catchable exception classes is the class of the exception or a superclass of the class of the exception.
Equivalently, acatch
clause will catch any exception object that is aninstanceof
(§15.20.2) one of its catchable exception classes.
The control transfer that occurs when an exception is thrown causes abrupt completion of expressions (§15.6) and statements (§14.1) until acatch
clause is encountered that can handle the exception; execution then continues by executing the block of thatcatch
clause. The code that caused the exception is never resumed.
All exceptions (synchronous and asynchronous) areprecise: when the transfer of control takes place, all effects of the statements executed and expressions evaluated before the point from which the exception is thrown must appear to have taken place. No expressions, statements, or parts thereof that occur after the point from which the exception is thrown may appear to have been evaluated.
If optimized code has speculatively executed some of the expressions or statements which follow the point at which the exception occurs, such code must be prepared to hide this speculative execution from the user-visible state of the program.
If nocatch
clause that can handle an exception can be found, then the current thread (the thread that encountered the exception) is terminated. Before termination, allfinally
clauses are executed and the uncaught exception is handled according to the following rules:
If the current thread has an uncaught exception handler set, then that handler is executed.
Otherwise, the methoduncaughtException
is invoked for theThreadGroup
that is the parent of the current thread. If theThreadGroup
and its parentThreadGroup
s do not overrideuncaughtException
, then the default handler'suncaughtException
method is invoked.
In situations where it is desirable to ensure that one block of code is always executed after another, even if that other block of code completes abruptly, atry
statement with afinally
clause (§14.20.2) may be used.
If atry
orcatch
block in atry
-finally
ortry
-catch
-finally
statement completes abruptly, then thefinally
clause is executed during propagation of the exception, even if no matchingcatch
clause is ultimately found.
If afinally
clause is executed because of abrupt completion of atry
block and thefinally
clause itself completes abruptly, then the reason for the abrupt completion of thetry
block is discarded and the new reason for abrupt completion is propagated from there.
The exact rules for abrupt completion and for the catching of exceptions are specified in detail with the specification of each statement in§14 (Blocks and Statements) and for expressions in§15 (Expressions) (especially§15.6).
Example 11.3-1. Throwing and Catching Exceptions
The following program declares an exception classTestException
. Themain
method of classTest
invokes thethrower
method four times, causing exceptions to be thrown three of the four times. Thetry
statement in methodmain
catches each exception that the thrower throws. Whether the invocation ofthrower
completes normally or abruptly, a message is printed describing what happened.
class TestException extends Exception { TestException() { super(); } TestException(String s) { super(s); }}class Test { public static void main(String[] args) { for (String arg : args) { try { thrower(arg); System.out.println("Test \"" + arg + "\" didn't throw an exception"); } catch (Exception e) { System.out.println("Test \"" + arg + "\" threw a " + e.getClass() + "\n with message: " + e.getMessage()); } } } static int thrower(String s) throws TestException { try { if (s.equals("divide")) { int i = 0; return i/i; } if (s.equals("null")) { s = null; return s.length(); } if (s.equals("test")) { throw new TestException("Test message"); } return 0; } finally { System.out.println("[thrower(\"" + s + "\") done]"); } }}
If we execute the program, passing it the arguments:
divide null not test
it produces the output:
[thrower("divide") done]Test "divide" threw a class java.lang.ArithmeticException with message: / by zero[thrower("null") done]Test "null" threw a class java.lang.NullPointerException with message: null[thrower("not") done]Test "not" didn't throw an exception[thrower("test") done]Test "test" threw a class TestException with message: Test message
The declaration of the methodthrower
must have athrows
clause because it can throw instances ofTestException
, which is a checked exception class (§11.1.1). A compile-time error would occur if thethrows
clause were omitted.
Notice that thefinally
clause is executed on every invocation ofthrower
, whether or not an exception occurs, as shown by the "[thrower(...) done]
" output that occurs for each invocation.