Programming Languages and Techniques (CIS120e) Lecture 25 Nov. 8, 2010 ExcepEons and the Java Abstract Stack Machine
Announcements Homework 8 (SpellChecker) is due Nov 15th. Midterm 2 is this Friday, November 12 th CIS120e / Fall 2010 2
ExcepEons Dealing with failure. CIS120e / Fall 2010 3
ExcepEons An excepeon is an object represeneng abnormal condieons. Its internal state describes what went wrong. Examples: NullPointPointerExcepEon, IllegalArgumentExcepEon, IOExcepEon Throwing an excepeon is an emergency exit from the current method. The excepeon propagates up the invocaeon stack unel it either reaches the top and the stack, in which case the program aborts with the error, or the excepeon is caught. Catching an excepeon lets callers take appropriate aceons to handle the abnormal circumstances. CIS120e / Fall 2010 4
Example class C {!!public void foo() {!!!bar();!!!system.out.println(!}!!public void bar() {!!!baz();!!!system.out.println( here in bar );!!}!!public void baz() {!!!throw new Exception();!!!System.out.println( here in baz );!!}! }! What happens if we do (new C()).foo();? CIS120e / Fall 2010 5
Workspace (new C()).foo();! Stack Heap CIS120e / Fall 2010 6
Workspace (new C()).foo();! Stack Heap CIS120e / Fall 2010 7
Workspace ().foo();! Stack Heap Allocate a new instance of C in the heap. CIS120e / Fall 2010 8
Workspace ().foo();! Stack Heap CIS120e / Fall 2010 9
Workspace bar();! Stack Heap Save a copy of the current workspace in the stack, leaving a hole, wricen _, where we return to. Push the this* pointer, followed by arguments (in this case none) onto the stack. *We ll explain the this pointer in more detail later. Suffice it to say that it s how we can find which code to run when an instance method like bar is invoked. CIS120e / Fall 2010 10
Workspace bar();! Stack Heap CIS120e / Fall 2010 11
Workspace baz();! here in bar );! Stack Heap CIS120e / Fall 2010 12
Workspace baz();! here in bar );! Stack Heap CIS120e / Fall 2010 13
Workspace throw new Exception();! here in baz );! Stack here in bar );! Heap CIS120e / Fall 2010 14
Workspace throw new Exception();! here in baz );! Stack here in bar );! Heap CIS120e / Fall 2010 15
Workspace throw ();! here in baz );! Stack here in bar );! Heap Exception! CIS120e / Fall 2010 16
Workspace throw ();! here in baz );! Discard the current workspace. Then, pop saved workspace frames off the stack, looking for the most recently pushed one that contains a try/catch block whose catch clause declares a supertype of the excepeon being thrown. If no matching catch is found, abort the program with an error. Stack here in bar );! Heap Exception! CIS120e / Fall 2010 17
Workspace Stack Heap Discard the current workspace. Then, pop saved workspace frames off the stack, looking for the most recently pushed one that contains a try/catch block whose catch clause declares a supertype of the excepeon being thrown. If no matching catch is found, abort the program with an error. here in bar );! Exception! CIS120e / Fall 2010 18
Workspace Stack Heap Discard the current workspace. Then, pop saved workspace frames off the stack, looking for the most recently pushed one that contains a try/catch block whose catch clause declares a supertype of the excepeon being thrown. If no matching catch is found, abort the program with an error. here in bar );! Try/Catch for ( )? Exception! No! CIS120e / Fall 2010 19
Workspace Stack Heap Discard the current workspace. Then, pop saved workspace frames off the stack, looking for the most recently pushed one that contains a try/catch block whose catch clause declares a supertype of the excepeon being thrown. If no matching catch is found, abort the program with an error. Try/Catch for ( )? Exception! No! CIS120e / Fall 2010 20
Workspace Stack Heap Try/Catch for ( )? No! Discard the current workspace. Exception! Then, pop saved workspace frames off the stack, looking for the most recently pushed one that contains a try/catch block whose catch clause declares a supertype of the excepeon being thrown. If no matching catch is found, abort the program with an error. CIS120e / Fall 2010 21
Workspace Stack Heap Program terminated with uncaught excepeon ( )! Discard the current workspace. Exception! Then, pop saved workspace frames off the stack, looking for the most recently pushed one that contains a try/catch block whose catch clause declares a supertype of the excepeon being thrown. If no matching catch is found, abort the program with an error. CIS120e / Fall 2010 22
Catching the ExcepEon class C {!!public void foo() {!!!bar();!!!system.out.println(!}!!public void bar() {!!!try {!!!!!!baz();!!!} catch (Exception e) { System.out.println( caught ); }!!!System.out.println( here in bar );!!}!!public void baz() {!!!throw new Exception();!!!System.out.println( here in baz );!!}! }! Now what happens if we do (new C()).foo();? CIS120e / Fall 2010 23
Workspace (new C()).foo();! Stack Heap CIS120e / Fall 2010 24
Workspace (new C()).foo();! Stack Heap CIS120e / Fall 2010 25
Workspace ().foo();! Stack Heap Allocate a new instance of C in the heap. CIS120e / Fall 2010 26
Workspace ().foo();! Stack Heap CIS120e / Fall 2010 27
Workspace bar();! Stack Heap Save a copy of the current workspace in the stack, leaving a hole, wricen _, where we return to. Push the this* pointer, followed by arguments (in this case none) onto the stack. *We ll explain the this pointer in more detail in the next lecture. Suffice it to say that it s how we can find which code to run when an object- local method like bar is invoked. CIS120e / Fall 2010 28
Workspace bar();! Stack Heap CIS120e / Fall 2010 29
Workspace try {! baz();! } catch (Exception e) { System.out.Println ( caught ); }! here in bar );! Stack Heap CIS120e / Fall 2010 30
Workspace try {! baz();! } catch (Exception e) { System.out.Println ( caught ); }! here in bar );! When execueng a try/catch block, push onto the stack a new workspace that contains all of the current workspace except for the try { } code. Stack Heap Replace the current workspace with the body of the try. CIS120e / Fall 2010 31
Workspace Stack Heap baz();! Body of the try. Everything else. When execueng a try/catch block, push onto the stack a new workspace that contains all of the current workspace except for the try { } code. Replace the current workspace with the body of the try. catch (Exception e) { System.out.Println ( caught ); }! here in bar );! CIS120e / Fall 2010 32
baz();! Workspace ConEnue execueng as normal. Stack catch (Exception e) { System.out.Println ( caught ); }! here in bar );! Heap CIS120e / Fall 2010 33
Workspace Stack Heap throw new Exception();! here in baz );! The top of the stack is off the bocom of the page catch (Exception e) { System.out.Println ( caught ); }! here in bar );! CIS120e / Fall 2010 34
Workspace Stack Heap throw new Exception();! here in baz );! catch (Exception e) { System.out.Println ( caught ); }! here in bar );! CIS120e / Fall 2010 35
Workspace Stack Heap throw ();! here in baz );! catch (Exception e) { System.out.Println ( caught ); }! here in bar );! Exception! CIS120e / Fall 2010 36
Workspace Stack Heap throw ();! here in baz );! Discard the current workspace. Then, pop saved workspace frames off the stack, looking for the most recently pushed one that contains a try/catch block whose catch clause declares a supertype of the excepeon being thrown. If no matching catch is found, abort the program with an error. catch (Exception e) { System.out.Println ( caught ); }! here in bar );! Exception! CIS120e / Fall 2010 37
Workspace Stack Heap Discard the current workspace. Then, pop saved workspace frames off the stack, looking for the most recently pushed one that contains a try/catch block whose catch clause declares a supertype of the excepeon being thrown. If no matching catch is found, abort the program with an error. catch (Exception e) { System.out.Println ( caught ); }! here in bar );! Try/Catch for ( )? Exception! No! CIS120e / Fall 2010 38
Workspace Stack Heap When a matching catch block is found, add a new binding to the stack for the excepeon variable declared in the catch. Then replace the workspace with catch body and the rest of the saved workspace. ConEnue execueng as usual. catch (Exception e) { System.out.Println ( caught ); }! here in bar );! Exception! Try/Catch for ( )? Yes! CIS120e / Fall 2010 39
Workspace Stack Heap { System.out.Println ( caught ); }! here in bar );! When a matching catch block is found, add a new binding to the stack for the excepeon variable declared in the catch. Then replace the workspace with catch body and the rest of the saved workspace. ConEnue execueng as usual. e! Exception! CIS120e / Fall 2010 40
Workspace Stack Heap { System.out.Println ( caught ); }! here in bar );! ConEnue execueng as usual. e! Exception! CIS120e / Fall 2010 41
Workspace Stack Heap { ; }! here in bar );! ConEnue execueng as usual. e! Exception! Console caught! CIS120e / Fall 2010 42
Workspace Stack Heap { ; }! here in bar );! We re sweeping a few details about lexical scoping of variables under the rug the scope of e is just the body of the catch, so when that is done, e must be popped from the stack. Console caught! e! Exception! CIS120e / Fall 2010 43
Workspace Stack Heap here in bar );! ConEnue execueng as usual. Exception! Console caught! CIS120e / Fall 2010 44
Workspace Stack Heap here in bar );! ConEnue execueng as usual. Exception! Console caught! CIS120e / Fall 2010 45
Workspace Stack Heap ;! Pop the stack when the workspace is done, returning to the saved workspace just aoer the _ mark. Exception! Console caught! here in bar! CIS120e / Fall 2010 46
Workspace Stack Heap ConEnue execueng as usual. Exception! Console caught! here in bar! CIS120e / Fall 2010 47
Workspace Stack Heap ConEnue execueng as usual. Exception! Console caught! here in bar! CIS120e / Fall 2010 48
Workspace Stack Heap ;! ConEnue execueng as usual. Exception! Console caught! here in bar! here in foo! CIS120e / Fall 2010 49
Workspace Stack Heap Program terminated normally. Exception! Console caught! here in bar! here in foo! CIS120e / Fall 2010 50
When No ExcepEon is Thrown If no excepeon is thrown while execueng the body of a try { } block, evaluaeon skips the corresponding catch block. i.e. if you ever reach a workspace where catch is the statement to run, just skip it: Workspace Workspace catch (Exception e) { System.out.Println ( caught ); }! here in bar );! here in bar );! CIS120e / Fall 2010 51
Catching ExcepEons There can be more than one catch clause associated with each try Matched in order, according to the dynamic type of the excepeon thrown. Helps refine the error handling try {! // do something with the IO library! } catch (FileNotFoundException e) {! // handle an absent file! } catch (IOException e) {! // handle other kinds of IO errors.! }! Good style: be as specific as possible about the excepeons you re handling. Avoid catch (Exception e) { } it s usually too generic! CIS120e / Fall 2010 52
ExcepEon Class Hierarchy Type of all throwable objects. Object Subtypes of ExcepEon must be declared. Throwable ExcepEon Error Fatal Errors, should never be caught. IOExcepEon RunEmeExcepEon IllegalArgumentExcepEon Subtypes of RunEmeExcepEon do not have to be declared. CIS120e / Fall 2010 53
Checked (Declared) ExcepEons ExcepEons that are subtypes of ExcepEon (but not RunEmeExcepEon) are called checked or declared. A method that might throw a checked excepeon must declare it using a throws clause in the method type. The method might raise a checked excepeon, either by: directly throwing such an excepeon public void maybedoit (String file) throws AnException {!!if ( ) throw new AnException(); // directly throw!! or, calling another method that might itself throw a checked excepeon public void dosomeio (String file) throws IOException {!!Reader r = new FileReader(file); // might throw!! CIS120e / Fall 2010 54
Unchecked (Undeclared) ExcepEons Subclasses of RunEmeExcepEon do not need to be declared via throws even if the method does not explicitly handle them. Many pervasive types of errors cause RunEmeExcepEons NullPointerExcepEon IndexOutOfBoundsExcepEon IllegalArgumentExcepEon public void mightfail (String file) {!!if (file.equals( dictionary.txt ) {!!!// file could be null!!!! The original intent was that such excepeons represent disastrous condieons from which it was impossible to sensibly recover CIS120e / Fall 2010 55
Declared vs. Undeclared? Tradeoffs in the sooware design process: Declared = becer documentaeon forces callers to acknowledge that the excepeon exists Undeclared = fewer staec guarantees but, much easier to refactor code In pracece: test- driven development encourages fail early/fail ooen model of code design and lots of code refactoring, so undeclared excepeons are prevalent. A good compromise? Declared excepeons for libraries, where the documentaeon and usage enforcement are criecal Undeclared for client- excepeons to facilitate more flexible code CIS120e / Fall 2010 56
Good Style for ExcepEons In Java, excepeons should be used to capture excep8onal circumstances Try/catch/throw incur performance costs and complicate reasoning about the program, don t use them when becer solueons exist Re- use exiseng excepeon types when they are meaningful to the situaeon e.g. use NoSuchElementExcepEon when implemeneng a container Define your own subclasses of ExcepEon when doing so can convey useful informaeon to possible callers that can handle the excepeon. It is ooen sensible to catch one excepeon and re- throw a different (more meaningful) kind of excepeon. e.g. when implemeneng WordScanner, we caught IOExcepEon and threw NoSuchElementExcepEon in the next() method. Catch excepeons as near to the source of failure as makes sense i.e. where you have the informaeon to deal with the excepeon Catch excepeons with as much precision as you can i.e. Don t do: try { } catch (ExcepEon e) { } instead do: try { } catch (IOExcepEon e) { } CIS120e / Fall 2010 57
Finally A finally clause of a try/catch/finally statement always gets run, regardless of whether there is no excepeon, a propagated excepeon, a caught excepeon, or even if the method returns from inside the try. Finally is most ooen used for releasing resources that might have been held/created by the try block: public void dosomeio (String file) {! FileReader r = null;! try {! r = new FileReader(file);! // do some IO! } catch (FileNotFoundException e) {! // handle the absent file! } catch (IOException e) {! // handle other IO problems! } finally {! if (r!= null) { // don t forget null check!! try { r.close(); } catch (IOException e) { }! }! }! }! 58
The Java Abstract Stack Machine 1. Class tables 2. Method invocaeons and this 3. StaEc members CIS120e / Fall 2010 59
Consider This Example public class Ctr {! private int x;! public Ctr () { x = 0; }! public void incby(int d) { x = x + d; }! public int get() { return x; }! }! public class Decr extends Ctr {! private int y;! public D (int inity) { y = inity; }! public void dec() { incby(-y); }! }! // somewhere in main:! Decr d = new Decr(2);! d.dec().get();! CIS120e / Fall 2010 60