CHAPTER 11
When a Java program violates the semantic constraints of the Java language, a Java Virtual Machine signals this error to the program as an exception. 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 Java: to provide portability and robustness. Instead, Java 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 be thrown from the point where it occurred and is said to be caught at the point to which control is transferred.
Java programs can also throw exceptions explicitly, using throw
statements (§14.16). This 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 class Throwable
or one of its subclasses; 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 by catch
clauses of try
statements (§14.18). During the process of throwing an exception, a Java Virtual Machine abruptly completes, one by one, any expressions, statements, method and constructor invocations, static 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. If no such handler is found, then the method uncaughtException
(§20.21.31) is invoked for the ThreadGroup
that is the parent of the current thread-thus every effort is made to avoid letting an exception go unhandled.
The Java exception mechanism is integrated with the Java synchronization model (§17), so that locks are released as synchronized
statements (§14.17) and invocations of synchronized
methods (§8.4.3.5, §15.11) complete abruptly.
This chapter describes the different causes of exceptions (§11.1). It details how exceptions are checked at compile time (§11.2) and processed at run time (§11.3). A detailed example (§11.4) is then followed by an explanation of the exception hierarchy and the standard exception classes (§11.5).
throw
statement (§14.16) was executed in Java code.
stop
of class Thread
(§20.20.16) was invoked
Throwable
and instances of its subclasses. These classes are, collectively, the exception classes.throws
clause for the method (§8.4.4) or constructor (§8.6.4)
must mention the class of that exception or one of the superclasses of the class of
that exception. This compile-time checking for the presence of exception handlers
is designed to reduce the number of exceptions which are not properly handled.
The unchecked exceptions classes are the class RuntimeException
and its subclasses, and the class Error
and its subclasses. All other exception classes are checked exception classes. The standard Java API defines a number of exception classes, both checked and unchecked. Additional exception classes, both checked and unchecked, may be declared by Java programmers. See §11.5 for a description of the Java exception class hierarchy and the exception classes defined by the standard Java API and Java Virtual Machine.
The checked exception classes named in the throws
clause are part of the contract between the implementor and user of the method or constructor. The throws
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 its throws
clause, to throw. 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 a throws
clause that is compatible with all the overridden declarations (§9.4).
Variable initializers for fields (§8.3.2) and static initializers (§8.5) must not result in a checked exception; if one does, a compile-time error occurs.
Error
and its
subclasses) are exempted from compile-time checking because they can occur at
many points in the program and recovery from them is difficult or impossible. A
Java program declaring such exceptions would be cluttered, pointlessly.
RuntimeException
and its subclasses) are
exempted from compile-time checking because, in the judgment of the designers
of Java, having to declare such exceptions would not aid significantly in establishing
the correctness of Java programs. Many of the operations and constructs of the
Java language can result in runtime exceptions. The information available to a
Java compiler, and the level of analysis the compiler performs, are usually not sufficient
to establish that such runtime exceptions cannot occur, even though this
may be obvious to the Java programmer. Requiring such exception classes to be
declared would simply be an irritation to Java 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 a NullPointerException
cannot occur, but it would be difficult for a 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 Java Language Specification.
catch
clause of a try
statement
(§14.18) that handles the exception.
A statement or expression is dynamically enclosed by a catch
clause if it appears within the try
block of the try
statement of which the catch
clause is a part, or if the caller of the statement or expression is dynamically enclosed by the catch
clause.
The caller of a statement or expression depends on where it occurs:
newInstance
that was executed to cause an object to be created.
static
variable, then the caller is the expression that used the class or interface so as to cause it to be initialized.
catch
clause handles an exception is determined by comparing the class of the object that was thrown to the declared type of the parameter of the catch
clause. The catch
clause handles the exception if the type of its parameter is the class of the exception or a superclass of the class of the exception. Equivalently, a catch
clause will catch any exception object that is an instanceof
(§15.19.2) the declared parameter type.
The control transfer that occurs when an exception is thrown causes abrupt completion of expressions (§15.5) and statements (§14.1) until a catch
clause is encountered that can handle the exception; execution then continues by executing the block of that catch
clause. The code that caused the exception is never resumed.
If no catch
clause handling an exception can be found, then the current thread (the thread that encountered the exception) is terminated, but only after all finally
clauses have been executed and the method uncaughtException
(§20.21.31) has been invoked for the ThreadGroup
that is the parent of the current thread.
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, a try
statement with a finally
clause (§14.18.2) may be used. If a try
or catch
block in a try
-finally
or try
-catch
-finally
statement completes abruptly, then the finally
clause is executed during propagation of the exception, even if no matching catch
clause is ultimately found. If a finally
clause is executed because of abrupt completion of a try
block and the finally
clause itself completes abruptly, then the reason for the abrupt completion of the try
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 and for expressions in §15 (especially §15.5).
Asynchronous exceptions are rare in Java. They occur only as a result of:
stop
methods of class Thread
(§20.20.15, §20.20.16) or ThreadGroup
(§20.21.8, §20.21.9)
InternalError
(§11.5.2.2) in the Java Virtual Machine
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
InternalError
is considered asynchronous so that it may be handled using the
same mechanism that handles the stop
method, as will now be described.
Java permits a small but bounded amount of execution to occur before an asynchronous exception is thrown. This delay 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 language.
A simple implementation might poll for asynchronous exceptions at the point of each control transfer instruction. Since a Java 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 paper Polling Efficiently on Stock Hardware by Mark Feeley, Proc. 1993 Conference on Functional Programming and Computer Architecture, Copenhagen, Denmark, pp. 179-187, is recommended as further reading.
Like all exceptions, asynchronous exceptions are precise (§11.3.1).
class TestException extends Exception {
TestException() { super(); }
TestException(String s) { super(s); }
} class Test { public static void main(String[] args) { for (int i = 0; i < args.length; i++) {
try { thrower(args[i]); System.out.println("Test \"" + args[i] + "\" didn't throw an exception"); } catch (Exception e) { System.out.println("Test \"" + args[i] + "\" threw a " + e.getClass() + "\n with message: " + e.getMessage()); } } }If we execute the test program, passing it the arguments:
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]"); } } }
divide null not testit 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 messageThis example declares an exception class
TestException
. The main
method of class Test
invokes the thrower
method four times, causing exceptions to be thrown three of the four times. The try
statement in method main
catches each exception that the thrower
throws. Whether the invocation of thrower
completes normally or abruptly, a message is printed describing what happened.
The declaration of the method thrower
must have a throws
clause because it can throw instances of TestException
, which is a checked exception class (§11.2). A compile-time error would occur if the throws
clause were omitted.
Notice that the finally
clause is executed on every invocation of thrower
, whether or not an exception occurs, as shown by the "[thrower(
...) done]
" output that occurs for each invocation
Throwable
(§11.5, §20.22), a direct subclass of Object
. The
classes Exception
and Error
are direct subclasses of Throwable
. The class
RuntimeException
is a direct subclass of Exception
.
The exception classes declared by the standard packages java.lang
, java.util
, java.io
and java.net
are called the standard exception classes.
Java programs can use the pre-existing exception classes in throw
statements, or define additional exception classes, as subclasses of Throwable
or of any of its subclasses, as appropriate. To take advantage of Java's compile-time checking for exception handlers, it is typical to define most new exception classes as checked exception classes, specifically as subclasses of Exception
that are not subclasses of RuntimeException
.
Exception
and RuntimeException
Exception
is the superclass of all the exceptions that ordinary programs
may wish to recover from.
RuntimeException
is a subclass of class Exception
. The subclasses
of RuntimeException
are unchecked exception classes.
Package java.lang
defines the following standard unchecked runtime exceptions, which, like all other classes in package java.lang
, are implicitly imported and therefore may be referred to by their simple names:
ArithmeticException
: An exceptional arithmetic situation has arisen, such as an integer division (§15.16.2) operation with a zero divisor.
ArrayStoreException
: An attempt has been made to store into an array component a value whose class is not assignment compatible with the component type of the array (§10.10, §15.25.1).
ClassCastException
: An attempt has been made to cast (§5.4, §15.15) a reference to an object to an inappropriate type.
IllegalArgumentException
: A method was passed an invalid or inappropriate argument or invoked on an inappropriate object. Subclasses of this class include:
IllegalThreadStateException:
A thread was not in an appropriate state for a requested operation.
NumberFormatException
: An attempt was made to convert a String
to a value of a numeric type, but the String
did not have an appropriate format.
IllegalMonitorStateException
: A thread has attempted to wait on (§20.1.6, §20.1.7, §20.1.8) or notify (§20.1.9, §20.1.10) other threads waiting on an object that it has not locked.
IndexOutOfBoundsException
: Either an index of some sort (such as to an array, a string, or a vector) or a subrange, specified either by two index values or by an index and a length, was out of range.
NegativeArraySizeException
: An attempt was made to create an array with a negative length (§15.9).
NullPointerException
: An attempt was made to use a null reference in a case where an object reference was required.
SecurityException
: A security violation was detected (§20.17).
java.util
defines the following additional standard unchecked runtime
exceptions:
java.util.EmptyStackException
: An attempt was made to access an element of an empty stack.
java.util.NoSuchElementException
: An attempt was made to access an element of an empty vector.
Exception
other than RuntimeException
are all
checked exception classes.
Package java.lang
defines the following standard exceptions, which, like all other classes in package java.lang
, are implicitly imported and therefore may be referred to by their simple names:
ClassNotFoundException
: A class or interface with a specified name could not be found (§20.3.8).
CloneNotSupportedException
: The clone
method (§20.1.5) of class Object
has been invoked to clone an object, but the class of that object does not implement the Cloneable
interface.
IllegalAccessException
: An attempt has been made to load a class using a string giving its fully qualified name, but the currently executing method does not have access to the definition of the specified class because the class is not public
and is in another package.
InstantiationException
: An attempt was made to create an instance of a class using the newInstance
method in class Class
, but the specified class object cannot be instantiated because it is an interface, is abstract
, or is an array.
InterruptedException
: The current thread was waiting, and another thread has interrupted the current thread, using the interrupt
method of class Thread
(§20.20.31).
java.io
defines the following additional standard exceptions:
java.io.IOException
: A requested I/O operation could not be completed normally. Subclasses of this class include:
java.io.EOFException
: End of file has been encountered before normal completion of an input operation.
java.io.FileNotFoundException
: A file with the name specified by a file name string or path was not found within the file system.
java.io.InterruptedIOException
: The current thread was waiting for completion of an I/O operation, and another thread has interrupted the current thread, using the interrupt
method of class Thread
(§20.20.31).
java.io.UTFDataFormatException
: A requested conversion of a string to or from Java modified UTF-8 format could not be completed (§22.1.15, §22.2.14) because the string was too long or because the purported UTF-8 data was not the result of encoding a Unicode string into UTF-8.
java.net
defines the following additional subclasses of
java.io.IOException
:
u java.net.MalformedURLException
: A string that was provided as a URL, or as part of a URL, had an inappropriate format or specified an unknown protocol.
java.net.ProtocolException
: Some aspect of a network protocol was not correctly carried out.
java.net.SocketException
: An operation involving a socket could not be completed normally.
java.net.UnknownHostException
: The name of a network host could not be resolved to a network address.
java.net.UnknownServiceException
: The network connection cannot support the requested service.
Error
Error
and its standard subclasses are exceptions from which ordinary
programs are not ordinarily expected to recover. The class Error
is a separate
subclass of Throwable
, distinct from Exception
in the class hierarchy, to allow
programs to use the idiom:
} catch (Exception e) {to catch all exceptions from which recovery may be possible without catching errors from which recovery is typically not possible.
Package java.lang
defines all the error classes described here. These classes, like all other classes in package java.lang
, are implicitly imported and therefore may be referred to by their simple names.
LinkageError
when a loading, linkage, preparation, verification or initialization
error occurs:
ClassFormatError
, ClassCircularityError
, and NoClassDefFoundError
are described there.
IllegalAccessError
, InstantiationError
, NoSuchFieldError
, and NoSuchMethodError
, all of which are subclasses of IncompatibleClassChangeError
, and, also, UnsatisfiedLinkError
.
VerifyError
is described there.
AbstractMethodError
.
ExceptionInInitializerError
if execution of a static initializer or of an initializer for a static
field results in an exception that is not an Error
or a subclass of Error
.
VirtualMachineError
when an internal error or resource limitation prevents
it from implementing the semantics of the Java Language. This language
specification and the Java Virtual Machine Specification define the following virtual
machine errors:
InternalError
: An internal error has occurred in a Java Virtual Machine, because of a fault in the software implementing the virtual machine, a fault in the underlying host system software, or a fault in the hardware. This error is delivered asynchronously when it is detected, and may occur at any point in a Java program.
OutOfMemoryError
: A Java Virtual Machine has run out of either virtual or physical memory, and the automatic storage manager wasn't able to reclaim enough memory to satisfy an object creation request.
StackOverflowError
: A Java Virtual Machine has run out of stack space for a thread, typically because the thread is doing an unbounded number of recursive invocations due to a fault in the executing program.
UnknownError
: An exception or error has occurred but, for some reason, a Java Virtual Machine is unable to report the actual exception or error.
OutOfMemoryError
and
attempt to recover from it, perhaps by carefully dropping references to objects.
We are exploring enhancements to Java to simplify handling of out-of-memory conditions. One possibility would be to support automatic suspension of a thread which encounters an OutOfMemoryError
and allow another thread to handle the error
situation. Such a technique might also permit a Java program to recover from a StackOverflowError
if this overflow does not result from a nonterminating recursion. Suggestions for other approaches are welcomed.
Contents | Prev | Next | Index
Java Language Specification (HTML generated by Suzette Pelouch on February 24, 1998)
Copyright © 1996 Sun Microsystems, Inc.
All rights reserved
Please send any comments or corrections to [email protected]