You are on page 1of 59

Exceptions in Java

Christian Ratliff <cratliff@delorme.com>

Sr. Technology Architect


Core Libraries Group
DeLorme Mapping
Presentation Sections

1. A lexicon and short history of exceptions.

2. Working with exceptions in Java.

3. Designing an effective exception class hierarchy.

4. Advanced exception handling.

Copyright (c) 2001 DeLorme 2


Section One

A lexicon and short history of exceptions.


Lexicon: Actors and Actions

Operation
A method which can possibly raise an exception.
Invoker
A method which calls operations and handles resulting exceptions.
Exception
A concise, complete description of an abnormal event.

Raise
Brings an exception from the operation to the invoker, called throw in
Java. Another very common word for this is emit.
Handle
Invoker’s response to the exception, called catch in Java.
Backtrack
Ability to unwind the stack frames from where the exception was raised to
the first matching handler in the call stack.
Copyright (c) 2001 DeLorme 4
Lexicon: Types of Exceptions

Hardware
Generated by the CPU in response to a fault (e.g. divide by zero, overflow,
segmentation fault, alignment error, etc).
Software
Defined by the developer to represent any other type of failure. These
exceptions often carry much semantic information.
Domain Failure
The inputs, or parameters, to the operation are considered invalid or
inappropriate for the requested operation.
Range Failure
Operation cannot continue, or output is possibly incorrect.
Monitor
Describes the status of an operation in progress, this is a mechanism for
runtime updates which is simpler than subthreads.

Copyright (c) 2001 DeLorme 5


Error Handling Before Exceptions

Error handling, before exceptions, took one of two forms:

Parameterized forms:
 Address of a subroutine to be called during an error.
 Name of a statement labels to jump to on error.
 Status variables changed by the operation, and then checked by
invoker at operation return.

Language-based forms:
 Fault subroutines tied to a type or instance.
 Fault target defined at compile time on the subroutine.
 PL/I condition statements.

Copyright (c) 2001 DeLorme 6


Problems with these Systems

Parameterized Calls Language Forms


 Not required to handle  One handler per exception
exceptional results per type or object.
 No way to detect at compile  Handler for each subroutine
time whether the exception is is predefined.
handled.  PL/I solution was not given to
 Limited number of condition- general use.
handler pairings.

How do we resolve these problems, and move from a system where


error handling is both inconsistent and ignorable to something
logically structured?

Copyright (c) 2001 DeLorme 7


Birth of Modern Exceptions

C.A.R. Hoare devised an exception processing system like:


Q1 otherwise Q2

John B. Goodenough described exceptions as:


 Hierarchical
 Classified
 Backtracking
 Explicitly Declared
 Resumable
 Defaultable

Copyright (c) 2001 DeLorme 8


Goodenough’s Notation
/* Declare an operation G, which can raise an exception X */
DECL G ENTRY (FIXED) [X:…];

/* Call G with parameter A and handle possible exceptions */


CALL G(A); [X: handler-action]
/* Handle an exception if A added to B overflows C */
C = (A + B); [OVERFLOW: handler-action]
/* Handle two possible overflow exceptions separately */
C = (A * (B * B) [OVERFLOW: handler-action1]); [OVERFLOW: handler-action2]
/* Handle exceptions from any element of the loop */
DO WHILE (…)
CALL G(A);
C = (A + B);
END; [X: …, OVERFLOW: …]
/* Handle an exception from any member of a statement group */
DO
CALL G(A);
C = (A + B);
END; [X: …, OVERFLOW: …]
Copyright (c) 2001 DeLorme 9
Advantages of this Notation

Enables transfer of control from location of the fault, to code


which knows how to handle that particular fault.
Exceptions cannot be ignored, they must be caught or the
application will terminate.
Separates the error management from the normal code.
Simplifies error processing by allowing entire blocks to be
combined inside one exception handler.
Exceptions are divided into three major groups:
 ESCAPE requires termination of the operation in progress.
 NOTIFY explicitly forbids termination of the operation, this is a
monitor.
 SIGNAL allows the invoker to either terminate or resume the operation
in progress.

Copyright (c) 2001 DeLorme 10


Questions for Section One

Copyright (c) 2001 DeLorme 11


Section Two
Working with exceptions in Java
Classifying Java Exceptions

Unchecked Exceptions Checked Exceptions


It is not required that these types Must either be caught by a
of exceptions be caught or method or declared in its
declared on a method. signature.
 Runtime exceptions can be  Placing exceptions in the method
generated by methods or by the signature harkens back to a
JVM itself. major concern for Goodenough.
 Errors are generated from deep  This requirement is viewed with
within the JVM, and often derision in the hardcore C++
indicate a truly fatal state. community.
 Runtime exceptions are a source  A common technique for
of major controversy! simplifying checked exceptions is
subsumption.

Copyright (c) 2001 DeLorme 13


Keywords for Java Exceptions

throws
Describes the exceptions which can be raised by a method.
throw
Raises an exception to the first available handler in the call stack,
unwinding the stack along the way.
try
Marks the start of a block associated with a set of exception handlers.
catch
If the block enclosed by the try generates an exception of this type,
control moves here; watch out for implicit subsumption.
finally
Always called when the try block concludes, and after any necessary catch
handler is complete.

Copyright (c) 2001 DeLorme 14


General Syntax
public void setProperty(String p_strValue) throws NullPointerException
{
if (p_strValue == null) { throw new NullPointerException(“...”); }
}

public void myMethod() {


MyClass oClass = new MyClass();

try {
oClass.setProperty(“foo”);
oClass.doSomeWork();

} catch (NullPointerException npe) {


System.err.println(“Unable to set property: “+npe.toString());
} finally {
oClass.cleanup();
}
}

Copyright (c) 2001 DeLorme 15


Canonical Example
public void foo() {
try { /* marks the start of a try-catch block */
int a[] = new int[2];
a[4] = 1; /* causes a runtime exception due to the index */
} catch (ArrayIndexOutOfBoundsException e) {

System.out.println("exception: " + e.getMessage());


e.printStackTrace();
}
}

/* This code also compiles, but throws an exception at runtime! It


* is both less obvious and more common (an off-by-one-error). */
public int[] bar() {
int a[] = new int[2];
for (int x = 0; x <= 2; x++) { a[x] = 0; }
return a;
}

Copyright (c) 2001 DeLorme 16


throw(s) Keyword

/* The IllegalArgumentException is considered unchecked, and


* even making it part of the signature will not alter that. */
public void setName(String p_strName) throws IllegalArgumentException
{
/* valid names cannot be zero length */
if (p_strName.length() == 0) {
throw new IllegalArgumentException(“…”);
}
m_strName = p_strName;
}

public void foo() {


setName(“”); /* No warning about unhandled exceptions. */
}

Copyright (c) 2001 DeLorme 17


throw(s) Keyword, part 2
/* Make a bad parameter exception class */
class NuttyParameterException extends Exception { … }

/* To really make an invoker pay attention, use a checked


* exception type rather than a Runtime Exception type, but
* you must declare that you will throw the type! */
public void setName(String p_strName) /* error here! */
{
/* valid names cannot be zero length */
if (p_strName == null || p_strName.length() == 0) {
throw new NuttyParameterException(“…”);
}
m_strName = p_strName;
}

Copyright (c) 2001 DeLorme 18


throw(s) Keyword, part 3
/* Make a bad parameter exception class */
class NuttyParameterException extends Exception { … }

/* To really make an invoker pay attention, use a checked


* exception type rather than a Runtime Exception type. */
public void setName(String p_strName) throws NuttyParameterException
{
/* valid names cannot be zero length */
if (p_strName == null || p_strName.length() == 0) {
throw new NuttyParameterException(“…”);
}
m_strName = p_strName;
}
/* Many of us will have an unquenchable desire to use a Runtime
* exception in the above, but resist! */
public void foo() {
setName(“”); /* This does result in an error. */
}

Copyright (c) 2001 DeLorme 19


try Keyword
/* The try statement marks the position of the first bytecode instruction
* protected by an exception handler. */
try {

UserRecord oUser = new UserRecord();


oUser.setName(“Fred Stevens”);
oUser.store();

/* This catch statement then marks the final bytecode instruction


* protected, and begins the list of exceptions handled. This info
* is collected and is stored in the exception table for the method. */
} catch (CreateException ce) {
System.err.println(“Unable to create user record in the database.”);
}

Copyright (c) 2001 DeLorme 20


catch Keyword
/* A simple use of a catch block is to catch the exception raised by
* the code from a prior slide. */
try {
myObject.setName(“foo”);

} catch (NuttyParameterException npe) {


System.err.println(“Unable to assign name: “ + npe.toString());
}

try { /* example 2 */
myObject.setName(“foo”);

} catch (NuttyParameterException npe) { /* log and relay this problem. */


System.err.println(“Unable to assign name: “ + npe.toString());
throw npe;
}

Copyright (c) 2001 DeLorme 21


catch Keyword, part 2
/* Several catch blocks of differing types can be concatenated. */
try {
URL myURL = new URL("http://www.mainejug.org");
InputStream oStream = myURL.openStream();
byte[] myBuffer = new byte[512];
int nCount = 0;

while ((nCount = oStream.read(myBuffer)) != -1) {


System.out.println(new String(myBuffer, 0, nCount));
}
oStream.close();

} catch (MalformedURLException mue) {


System.err.println("MUE: " + mue.toString());
} catch (IOException ioe) {
System.err.println("IOE: " + ioe.toString());
}

Copyright (c) 2001 DeLorme 22


finally Keyword
URL myURL = null;
InputStream oStream = null;

/* The prior sample completely neglected to discard the network


* resources, remember that the GC is non-determinstic!! */
try {
/* Imagine you can see the code from the last slide here... */

} finally { /* What two things can cause a finally block to be missed? */


/* Since we cannot know when the exception occurred, be careful! */
try {
oStream.close();
} catch (Exception e) {
}
}

Copyright (c) 2001 DeLorme 23


finally Keyword, part 2
public bool anotherMethod(Object myParameter) {

try { /* What value does this snippet return? */


myClass.myMethod(myParameter);
return true;

} catch (Exception e) {
System.err.println(“Exception in anotherMethod() “+e.toString());
return false;

} finally {
/* If the close operation can raise an exception, whoops! */
if (myClass.close() == false) {
break;
}
}
return false;
}

Copyright (c) 2001 DeLorme 24


finally Keyword, part 3
public void callMethodSafely() {

while (true) { /* How about this situation? */


try {
/* Call this method until it returns false. */
if (callThisOTherMethod() == false) {
return;
}

} finally {
continue;
}
} /* end of while */
}

Copyright (c) 2001 DeLorme 25


Steps of try…catch…finally

Every try block must have at least one catch or finally block
attached.
If an exception is raised during a try block:
 The rest of the code in the try block is skipped over.
 If there is a catch block of the correct, or derived, type in this stack
frame it is entered.
 If there is a finally block, it is entered.
 If there is no such block, the JVM moves up one stack frame.
If no exception is raised during a try block, and there is no
System.exit() statement:
 If there is a matching finally block it is entered.

Copyright (c) 2001 DeLorme 26


Questions for Section Two

??

Copyright (c) 2001 DeLorme 27


Section Three
Designing an effective exception class hierarchy.
Java Exception Hierarchy
Throwable The base class for all exceptions, it is required for a class to be
the rvalue to a throw statement.

Error Any exception so severe it should be allowed to pass


uncaught to the Java runtime.

Exception Anything which should be handled by the invoker is of this


type, and all but five exceptions are.

j a v a .la n g .T h r o w a b l e

j a v a .la n g .E r r o r j a v a .la n g . E x c e p t io n

j a v a .la n g .T h r e a d D e a t h j a v a .la n g .R u n t im e E x c e p t io n j a v a .io .I O E x c e p t io n

j a v a . la n g .N u llP o in t e r E x c e p t io n j a v a . la n g .I lle g a lA r g u m e n t E x c e p t io n j a v a .io .F ile N o t F o u n d E x c e p t io n

Copyright (c) 2001 DeLorme 29


Creating your own exception class
/* You should extend RuntimeException to create an unchecked exception,
* or Exception to create a checked exception. */
class MyException extends Exception {

/* This is the common constructor. It takes a text argument. */


public MyException(String p_strMessage) {
super(p_strMessage);
}

/* A default constructor is also a good idea! */


public MyException () {
super();
}

/* If you create a more complex constructor, then it is critical


* that you override toString(), since this is the call most often
* made to output the content of an exception. */

Copyright (c) 2001 DeLorme 30


Three Critical Decisions

How do you decide to raise an exception rather than return?


1. Is the situation truly out of the ordinary?
2. Should it be impossible for the caller to ignore this problem?
3. Does this situation render the class unstable or inconsistent?
Should you reuse an existing exception or create a new type?
1. Can you map this to an existing exception class?
2. Is the checked/unchecked status of mapped exception acceptable?
3. Are you masking many possible exceptions for a more general one?
How do you deal with subsumption in a rich exception hierarchy?
1. Avoid throwing a common base class (e.g. IOException).
2. Never throw an instance of the Exception or Throwable classes.

Copyright (c) 2001 DeLorme 31


An Example of Return v. Raise
try {
InputStream oStream = new URL("http://www.mainejug.org").openStream();
byte[] myBuffer = new byte[512];
StringBuffer sb = new StringBuffer();
int nCount = 0;

while ((nCount = oStream.read(myBuffer)) != -1) {


sb.append(new String(myBuffer));
}
oStream.close();
return sb.toString(); /* if sb.length() == 0 is NOT an exception. */

/* These, on the other hand, are certainly exceptional conditions. */


} catch (MalformedURLException mue) {
throw mue;
} catch (IOException ioe) {
throw ioe;
}

Copyright (c) 2001 DeLorme 32


Mapping to an Exception Class

When you attempt to map your situation onto an existing


Exception class consider these suggestions:
 Avoid using an unchecked exception, if it is important enough to
explicitly throw, it is important enough to be caught.
 Never throw a base exception class if you can avoid it:
RuntimeException, IOException, RemoteException, etc.
 Be certain your semantics really match. For example,
javax.transaction.TransactionRolledBackException, should not be
raised by your JDBC code.
 There is no situation which should cause you to throw the Exception
or Throwable base classes. Never.

Copyright (c) 2001 DeLorme 33


Using Unchecked Exceptions

Use unchecked exceptions to indicate a broken contract:

public void setName(String p_strName) {


/* This is a violated precondition. */
if (p_strName == null || p_strName.length() == 0) {
throw new InvalidArgumentException(“Name parameter invalid!”);
}
}

Be careful about creating a type derived from RuntimeException.

A class derived from AccessControlException is implicitly unchecked


because its parent class derives from RuntimeException.

Copyright (c) 2001 DeLorme 34


Simple Type Subsumption
/* Since UnknownHostException extends IOException, the catch block
* associated with the former is subsumed. */
try {
Socket oConn = new Socket(“www.sun.com”, 80);
} catch (IOException ioe) {
} catch (UnknownHostException ohe) {
}

/* The correct structure is to arrange the catch blocks with the most
* derived class first, and base class at the bottom. */
try {
Socket oConn = new Socket(“www.sun.com”, 80);
} catch (UnknownHostException ohe) {
} catch (IOException ioe) {
}

Copyright (c) 2001 DeLorme 35


A Tricky Subsumption Problem
/* The catch block can perform any number of functions, a common pair is
* exception encapsulation and rethrow. */
try {
Connection oConnection = MagicPool.getInstance().getConnection();
Statement oStatement = oConnection.createStatement(“...”);

if (oStatement.executeUpdate() != 1) {
throw new CreateException(“Account could not be created.”);
}

/* Why is there a possible subsumption here? */


} catch (SQLException sqle) {
throw new CreateException(“Unable to create requested account, due to
internal error: “ + sqle.toString());
} catch (CreateException ce) {
throw ce;
} /* You know what we need here, eh? */

Copyright (c) 2001 DeLorme 36


Avoiding Type Subsumption
try {
Connection oConnection = MagicPool.getInstance().getConnection();
Statement oStatement = oConnection.createStatement(“...”);

if (oStatement.executeUpdate() != 1) {
throw new CreateException(“Account could not be created.”);
}
/* If this rethrow was missing, we would have a problem. */
} catch (CreateException ce) {
throw ce;
} catch (SQLException sqle) {
throw new CreateException(“SQL error in creating: “+sqle.toString());
}

/* This avoids a subsumption, if CreateException is derived from


* SQLException. Above is a good technique for handling this problem. */

Copyright (c) 2001 DeLorme 37


Subsumption Is Good Too!
public String getContent(String p_strURL)
throws MalformedURLException, IOException
{
URL myURL = null;
InputStream oStream = null;
/* Imagine more code here. */
}

If the code calling this is driven by a console application then subsuming


the MalformedURLException makes the code easier to write. The same
error text is output regardless of type.
If, on the other hand, the code is in use by a GUI, then catching the two
exceptions aids the development of features like URL repair. The
IOException is fatal, but the user can possibly resolve the URL problem!
Adrian says, “This example stinks.”

Copyright (c) 2001 DeLorme 38


Type Encapsulation

Because JDBC objects can raise lots of types of checked and


unchecked exceptions, and because they encapsulate resources
which must be released quickly, this pattern emerges:
public void load(PrimaryKey p_oKey) throws CreateException {
Connection oConnection = null;
Statement oStatement = null;
try {
/* Imagine code here! */
} catch (CreateException ce) {
throw ce;
} catch (ClassNotFoundException cnfe) {
throw new CreateException(“Caught Class!Found”+cnfe.toString());
} catch (SQLException sqle) {
throw new CreateException(“Caught SQLException”+sqle.toString());
} finally {
try { oStatement.close(); } catch (Exception e) { }
try {oConnection.close(); } catch (Exception e) { }
}
}
Copyright (c) 2001 DeLorme 39
Questions for Section Three

???

Copyright (c) 2001 DeLorme 40


Section Four
Advanced Exception Handling
The Utility of Backtracking

Backtracking is the process by which the stack frame is unwound


in the presence of an unhandled exception.

This process has some important properties:

 Objects created on the stack are discarded to the GC.


 Methods which cannot handle the exception are cleaned up implicitly.
 Each stack frame has the ability to subsume the exception.
 The end of the line is the JVM, which logs unhandled exceptions.

Under C++, each object discarded is immediately, and fully,


destroyed. This is a key problem for Java, and C#:

Copyright (c) 2001 DeLorme 42


finally and finalize(), siblings?

Java’s garbage collector (GC) offers each method a type of


destructor called ‘finalizer()’.

It is called with neither timing nor order guarantees, by the JVM.

This is called non-deterministic finalization and gives rise to serious


problems with Java objects which encapsulate OS resources:
network, graphics, and database objects.

Enter the finally block:


try {
/* Insert code here. */
} finally {
myResource.close();
}

Copyright (c) 2001 DeLorme 43


Bytecode Layout

Each method has a table of exception information at the start of it:


 start_pc - where a try block begins
 end_pc - where the try block ends, just before the first catch
 catch_pc - the location of a catch block
 catch_type - the class type caught by this catch block.

If a finally block is in use, then each statement which can exit the
try block has a special bytecode instruction attached to it (jsr).
This calls the special finally subroutine.

It is easy to see how a proliferation of try/catch blocks and many


finally blocks can quickly grow the code and the exception table on
the method.

Copyright (c) 2001 DeLorme 44


Bytecode Layout, part 2
public void foo() {
try { /* marks the start of a try-catch block: start_pc */

int a[] = new int[2];


a[4] = 1; /* causes a runtime exception due to the index */

/* end of the code in the try block: end_pc */

} catch (ArrayIndexOutOfBoundsException e) {/* catch_pc, catch_type */


System.out.println(“AIOOBE = " + e.getMessage());

} catch (NullPointerException npe) { /* catch_pc, catch_type */


System.out.println(“NPE = “ + npe.toString();
}
}

Copyright (c) 2001 DeLorme 45


Performance Issues

At a macro level you can make it easier on a JIT compiler by doing


the following:
 Do not use exceptions to manage flow of control: exit a loop with a
status variable rather than raising an exception.
 Place try blocks outside of a while loop, rather than inside it.
 If you use a finally block, avoid having many exit paths in the content
of the block. Remember that each exit point has a JSR attached to it.
 The single largest exception cost in a non-native runtime is the
creation of the exception, not the catching of it.
In general avoid exceptions in the tight, fast code of your
implementation. While the cost is minimal in JVM, the price rises
rapidly in the JIT…

Copyright (c) 2001 DeLorme 46


Exceptions and JIT Optimization

Optimizing a Java program at runtime, within the JIT, requires a


process called “path analysis”.
A path analysis graph describes the structure of the method in the
form of a graph. Each of the canonical control structures (e.g. if,
for, while, …) creates new nodes and edges on the graph.
In the presence of exceptions, new nodes and edges can be
created for each and every Potentially Excepting Instruction (PEI)
in the method encountered.
Considering the number of both checked an unchecked exceptions,
these secondary, exceptional, paths can proliferate quickly.

The larger the path analysis graph, the more difficult it is for the
JIT compiler to optimize the Java application.

Copyright (c) 2001 DeLorme 47


Bytecode to Machine Code

When the JIT compiler is generating machine code from the


bytecode it is optimized over and over again.
This optimization takes advantage of the path analysis graph, and
potentially reorders the work of a method.
Java’s clear and precise specifications for exception handling deter
reorder-based optimization. This is because program state must be
correct before each PEI is invoked. (Make your eyes big and say,
OOHH!)
To really understand what all this means I would advise reading
the presentation:
 The Evolution of Optimization and Parallelization technologies for Java,
or why Java for High Performance Computing is not an oxymoron! by
IBM’s Vivek Sarkar.

Copyright (c) 2001 DeLorme 48


Why Runtime Exceptions are Not Checked

11.2.2
The runtime exception classes (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.

Copyright (c) 2001 DeLorme 49


Issues in Multithreaded Code
class MyThread implements Runnable {
public MyTask m_oTask = null;
public void run() {
if (m_oTask == null) {
throw new IllegalStateException(“No work to be performed!”);
} else {
/* Do the work of the thread. */
}
}
}

public void foo() {


MyThread oThread = new MyThread();
/* There is no way to get the exception from the run() method! */
new Thread(oThread).start(); /* Good reason for Runtime choice!! */
}

Copyright (c) 2001 DeLorme 50


Use a Callback Pattern
interface ThreadCallback {
public void threadException(Thread p_oThread, Exception p_oException);
public void threadSuccess(Thread p_oThread);
}

public MySubthread implements Runnable {


ThreadCallback m_oTarget = null; /* The target of our status info. */
public MySubthread(ThreadCallback p_oTarget) {
m_oTarget = p_oTarget;
}
public void run() {
try {
/* work is done here. */
} catch (SomeException se) {
m_oTarget.threadException(this, se); /* inform about problem. */
return;
}
m_oTarget.threadSuccess(this); /* indicate all went well! */
}
Copyright (c) 2001 DeLorme 51
Use the ThreadGroup class

Threads can be tied to an instance of the ThreadGroup class. This


instance is notified about any uncaught exceptions by one of its
member threads:

class java.lang.ThreadGroup {
/* lots of other methods deleted… */
public void uncaughtException(Thread t, Throwable e);
}
/* The thread startup will change to this: */
new Thread(oMyThreadGroup, oMyThread).start();

You can derive from ThreadGroup, and make your own class with its
own implementation of uncaughtException().
Then you can implement the listener pattern in your derived class and
broadcast exception events to interested parties.

Copyright (c) 2001 DeLorme 52


Exceptions and RMI

Owing to the presenters limited experience with RMI, David Ezzio will
speak for a moment on this interesting problem.

Copyright (c) 2001 DeLorme 53


Questions for Section Four

????

Copyright (c) 2001 DeLorme 54


Bibliography
Material for further reading

Links to this material is at:


http://www.backflip.com/members/cratliff
Section One

Goodenough, John B. Exception Handling: Issues and a Proposed


Notation. Communications of the ACM, 18(12), Dec 1975.

W. Kahan & J. Darcy. How Java’s Floating-Point Hurts Everyone


Everywhere. ACM 1998 Workshop on Java for High-Performance Network
Computing, March 1998.

Copyright (c) 2001 DeLorme 56


Section Two

R. Cartwright, E. Allen, and K. Charter. Intermediate Programming


(C212) Lecture Notes. Department of Computer Science, Rice
University, Spring 2001.

M. Robillard and G. Murphy. Analyzing Exception Flow in Java


Programs. Department of Computer Science, University of British
Columbia, 2 March 1999.

T. Suydam. Java Tip 91: Use nested exceptions in a multitiered


environment. JavaWorld, April 2001.

B. Venners. Under the Hood: Try-finally clauses defined and


demonstrated. JavaWorld, February 1997.

Copyright (c) 2001 DeLorme 57


Section Three

J. Gosling, B. Joy, G. Steele & G. Bracha. The Java Language


Specification, Second Edition. Sun Microsystems, 2000.

Copyright (c) 2001 DeLorme 58


Section Four

C. Austin & M. Pawlan. Advanced Programming for the Java2 Platform.


Addison Wesley, September 2000.
J-D. Choi, D. Grove, M. Hind, and V. Sarkar. Efficient and Precise Modeling of
Exceptions for the Analysis of Java Programs. IBM T.J. Watson Research Center.
M. Gupta, J-D. Choi, and M. Hind. Optimizing Java Programs in the
Presence of Exceptions. European Conference on Object-Oriented
Programming, Cannes France, June 14-16 2000.
P. Haggar. Multithreaded Exception Handling in Java. IBM Corporation.
V. Sarkar. Evolution of Optimization and Parallelization Technologies
for Java. IBM T.J. Watson Research Center, May 2000.
T. Suydam. Use nested exceptions in a multitiered environment.
JavaWorld.

Copyright (c) 2001 DeLorme 59

You might also like