59
Exceptions in Java Christian Ratliff <cratliff@delorme.com> Sr. Technology Architect Core Libraries Group DeLorme Mapping

Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Embed Size (px)

Citation preview

Page 1: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Exceptions in Java

Christian Ratliff <[email protected]>

Sr. Technology ArchitectCore Libraries GroupDeLorme Mapping

Page 2: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 2

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.

Page 3: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Section One

A lexicon and short history of exceptions.

Page 4: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 4

Lexicon: Actors and Actions

OperationA method which can possibly raise an exception.

InvokerA method which calls operations and handles resulting exceptions.

ExceptionA concise, complete description of an abnormal event.

RaiseBrings an exception from the operation to the invoker, called throw in Java. Another very common word for this is emit.

HandleInvoker’s response to the exception, called catch in Java.

BacktrackAbility to unwind the stack frames from where the exception was raised to the first matching handler in the call stack.

Page 5: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 5

Lexicon: Types of Exceptions

HardwareGenerated by the CPU in response to a fault (e.g. divide by zero, overflow, segmentation fault, alignment error, etc).

SoftwareDefined by the developer to represent any other type of failure. These exceptions often carry much semantic information.

Domain FailureThe inputs, or parameters, to the operation are considered invalid or inappropriate for the requested operation.

Range FailureOperation cannot continue, or output is possibly incorrect.

MonitorDescribes the status of an operation in progress, this is a mechanism for runtime updates which is simpler than subthreads.

Page 6: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 6

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.

Page 7: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 7

Problems with these Systems

Parameterized Calls Not required to handle

exceptional results No way to detect at

compile time whether the exception is handled.

Limited number of condition-handler pairings.

Language Forms One handler per

exception per type or object.

Handler for each subroutine is predefined.

PL/I solution was not given to general use.

How do we resolve these problems, and move from a system where error handling is both inconsistent and ignorable to something logically structured?

Page 8: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 8

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

Page 9: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 9

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: …]

Page 10: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 10

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.

Page 11: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 11

Questions for Section One

??

Page 12: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Section Two

Working with exceptions in Java

Page 13: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 13

Classifying Java Exceptions

Unchecked ExceptionsIt is not required that these types of exceptions be caught or declared on a method.

Runtime exceptions can be generated by methods or by the JVM itself.

Errors are generated from deep within the JVM, and often indicate a truly fatal state.

Runtime exceptions are a source of major controversy!

Checked ExceptionsMust either be caught by a method or declared in its signature.

Placing exceptions in the method signature harkens back to a major concern for Goodenough.

This requirement is viewed with derision in the hardcore C++ community.

A common technique for simplifying checked exceptions is subsumption.

Page 14: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 14

Keywords for Java Exceptions

throwsDescribes the exceptions which can be raised by a method.

throwRaises an exception to the first available handler in the call stack, unwinding the stack along the way.

tryMarks the start of a block associated with a set of exception handlers.

catchIf the block enclosed by the try generates an exception of this type, control moves here; watch out for implicit subsumption.

finallyAlways called when the try block concludes, and after any necessary catch handler is complete.

Page 15: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 15

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();

}}

Page 16: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 16

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;

}

Page 17: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 17

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. */

}

Page 18: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 18

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;

}

Page 19: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 19

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. */}

Page 20: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 20

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.”);

}

Page 21: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 21

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;

}

Page 22: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 22

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());

}

Page 23: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 23

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) {

}

}

Page 24: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 24

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;

}

Page 25: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 25

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 */

}

Page 26: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 26

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.

Page 27: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 27

Questions for Section Two

? ?? ?

Page 28: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Section Three

Designing an effective exception class hierarchy.

Page 29: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 29

Java Exception Hierarchy

j ava.lang.ThreadDeath

java.lang.Error

java.lang.N ullPointerEx ception java.lang.I llegalArgum entEx ception

java.lang.R untim eEx ception

java.io .FileN otFoundEx ception

java.io .I OEx ception

java.lang.Ex ception

java.lang.Throw able

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.

Page 30: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 30

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. */

Page 31: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 31

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.

Page 32: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 32

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;

}

Page 33: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 33

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.

Page 34: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 34

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.

Page 35: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 35

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) {

}

Page 36: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 36

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? */

Page 37: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 37

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. */

Page 38: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 38

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.”

Page 39: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 39

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) { }

}}

Page 40: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 40

Questions for Section Three

? ? ?? ? ?

Page 41: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Section Four

Advanced Exception Handling

Page 42: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 42

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#:

Page 43: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 43

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();}

Page 44: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 44

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.

Page 45: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 45

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();

}

}

Page 46: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 46

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…

Page 47: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 47

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.

Page 48: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 48

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.

Page 49: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 49

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.

Page 50: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 50

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!! */

}

Page 51: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 51

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! */

}

Page 52: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 52

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.

Page 53: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 53

Exceptions and RMI

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

Page 54: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 54

Questions for Section Four

? ? ? ?? ? ? ?

Page 55: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Bibliography

Material for further reading

Links to this material is at:http://www.backflip.com/members/cratliff

Page 56: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 56

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.

Page 57: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 57

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.

Page 58: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 58

Section Three

J. Gosling, B. Joy, G. Steele & G. Bracha. The Java Language Specification, Second Edition. Sun Microsystems, 2000.

Page 59: Exceptions in Java Christian Ratliff Sr. Technology Architect Core Libraries Group DeLorme Mapping

Copyright (c) 2001 DeLorme 59

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.