Java Programming/Nesting Exceptions
Navigate Exceptions topic: ) |
When an exception is caught, the exception contains the stack-trace, which describes the error and shows where the exception happened, where the problem is, where the application programmer should look to fix the problem.
Sometime it is desirable to catch an exception and throw an other new exception. This is a kind of exception conversion, from one exception to an other.
For example, calling a remote object using RMI, the calling method has to deal with RemoteException
which is thrown if something is wrong during the communication. For the application point of view, RemoteException
has no meaning, it should be transparent to the application that a remote object was used or not. So the RemoteException
should be converted to an application exception.
This conversion can also hide, where the error is originated. The stack-trace starts, when the exception is thrown. So when we catch and throw a new exception, the stack-trace starts at when the new exception was thrown, losing the original stack-trace. This was true with the earlier version of Java (Before 1.4). With the current version, a so called chained exception facility capabilities were build in the Throwable
class.
A throwable contains a snapshot of the execution stack of its thread at the time it was created. It can also contain a message string that gives more information about the error. Finally, it can contain a cause: another throwable that caused this throwable to get thrown. The cause facility is new in release 1.4. It is also known as the chained exception facility, as the cause can, itself, have a cause, and so on, leading to a "chain" of exceptions, each caused by another.
![]() |
public applicationMethod() throws ApplicationException {
try { //... callRemoteObjectMethod(); //... } catch ( RemoteException e ) { throw new ApplicationException( e ); } } |
The above code is an example of the nesting exception. When the ApplicationException
is thrown, by passing in the RemoteException
object reference as a parameter, the RemoteException
is nested in the newly created ApplicationException
, its stack-trace is appended together.
When the ApplicationException
is caught, its stack-trace contains the original RemoteException
's stack-trace.
A cause can be associated with a throwable in two ways: via a constructor that takes the cause as an argument, or via the initCause(Throwable) method. New throwable classes that wish to allow causes to be associated with them should provide constructors that take a cause and delegate (perhaps indirectly) to one of the Throwable constructors that takes a cause. For example:
![]() |
try {
lowLevelOp(); } catch (LowLevelException le) { throw new HighLevelException(le); // Chaining-aware constructor } |
Because the initCause method is public, it allows a cause to be associated with any throwable, even a "legacy throwable" whose implementation predates the addition of the exception chaining mechanism to Throwable. For example:
![]() |
try {
lowLevelOp(); } catch (LowLevelException le) { throw (HighLevelException) new HighLevelException().initCause(le); // Legacy constructor } |
Further, as of release 1.4, many general purpose Throwable classes (for example Exception, RuntimeException, Error
) have been retrofitted with constructors that take a cause. This was not strictly necessary, due to the existence of the initCause method, but it is more convenient and expressive to delegate to a constructor that takes a cause.
By convention, class Throwable
and its subclasses have two constructors, one that takes no arguments and one that takes a String argument that can be used to produce a detail message. Further, those subclasses that might likely have a cause associated with them should have two more constructors, one that takes a Throwable
(the cause), and one that takes a String (the detail message) and a Throwable
(the cause).
Also introduced in release 1.4 is the getStackTrace()
method, which allows programmatic access to the stack trace information that was previously available only in text form, via the various forms of the printStackTrace()
method. This information has been added to the serialized representation of this class so getStackTrace
and printStackTrace
will operate properly on a throwable that was obtained by deserialization.