1 / 63

Introduction to Computer Science I Topic 16: Exception Handling

Introduction to Computer Science I Topic 16: Exception Handling. Prof. Dr. Max Mühlhäuser Dr. Guido Rößling. Overview. Errors and their classification Error handling without language support and its problems Basics of error handling with language support in Java

gigi
Download Presentation

Introduction to Computer Science I Topic 16: Exception Handling

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Introduction to Computer Science ITopic 16: Exception Handling Prof. Dr. Max Mühlhäuser Dr. Guido Rößling

  2. Overview • Errors and their classification • Error handling without language support and its problems • Basics of error handling with language support in Java • Advantages of error handling with language support in Java • Summary

  3. Lexical errors: Wrong or unknown words are used in program code // ... int[] result = neu int[5]; result.size(); // ... Syntax errors: Wrong order of the words in program statements ... move(); public static voidmain(String[] args) { // … } ... Classification of errors Lexical and syntactical errors are discovered and signaled by the compiler

  4. Run-time errors: Any extraordinary event that occurs during program execution and disturbs the ordinary control flow error termination Division by 0 A non-existing graphical object shall be painted Intention errors: Program runs normally, but returns wrong results Classification of errors

  5. Dealing with errors is an important part of software development: Quality assurance! The usual reaction to untreated exceptions is a program crash This may be better than incorrect results that remain unnoticed for a long time Complex programs and distributed applications without any provision for handling exceptions are inacceptable Telecommunication systems Guidance and control systems, e.g., for rockets or nuclear plants Programs that treat errors gracefully are called robust Error Handling, Bugs and Debugging

  6. This lecture  catching and resolving runtime errors Heavy-weigth vs. light-weight errors Next lecture  Intention errors: test or verify that the software does what it is supposed to do Bug: name for all types of all program errors Origin: A dead moth (not really a “bug”) in a relais caused a malfunction. Usually hard to find, „100% bug free“ is close to impossible Debugging = searching for errors Both words go back to Grace Hopper Error Handling, Bugs and Debugging

  7. Heavyweight runtime errors • Two types of heavyweight programming errors: • System faults: faults in the Java VM, lack of free memory, … • Not the application programmer’s fault • Cannot be caught and lead directly to a program crash • Programming faultsafter which a continuation is not possible • A required class is not available

  8. Lightweight errors • Lightweight errors (also called exceptions) are errors which can be caught in the program; continuing the program is possible after fixing the error problem: input of a wrong file name by the user solution: repeat input problem: wrong data in a file that can be ignored, e.g., uninterpretable image or audio signal solution: Ignore the data problem: network connection crashes solution: reconnect

  9. Some typical exceptions public void printPerson() { Person aPerson = null; printName(aPerson); // … } public void printName(Person p) { System.out.println(p.name); } • Problem: sending a message to "null" • Result: NullPointerException • Access to a method or instance variable of a non-existing object (null) • Effectively there was an attempt to access "null.name" • The existence of the object should be checked before access!

  10. int[] matriculationNumber = new int[27]; for (int i = 0; i <= 27; i++) System.out.println(matriculationNumber[i]); Some typical exceptions • Problem: illegal array access with i == 27 • Result: ArrayIndexOutOfBoundsException • Only positions i with 0 <= i < array.length are valid • Especially tricky is the case of call parameters • Always test how many arguments were passed (args.length)

  11. Some typical exceptions public static void main(String[] args) { int count; count = Integer.parseInt(args[1]); // ... } code carries potential for multiple errors! Problem 1: illegal array access if no parameters were passed to the program. In this case, args has no elements - accessing args[1] fails Result 1: ArrayIndexOutOfBoundsException Problem 2: Attempt to parse a non-number if args[1] is e.g., "Hello". Text cannot be transformed into a number Result 2: NumberFormatException

  12. Exception handling • Exception handling can be done… • without language support • In languages such as C or Pascal • with language support • In languages such as Ada, Smalltalk, Java • In the following, we will: • Consider the problems of error handling without language support • Introduce error handling with dedicated language support and its advantages in Java

  13. Overview • Errors and their classification • Error handling without language support and its problems • Basics of error handling with language support in Java • Advantages of error handling with language support in Java • Summary

  14. Error handling without language support • Two possibilities forerror signaling: • Program crash (!) – The extreme case are functions that do not signal errors at all but simply terminate the program: • E.g., access to a non-existing file led to a program crash in older versions of Pascal • Errors are signaled in many languages by means of unusual return codes (e.g., –1 instead of a positive number) • Catching and handling of errors: • Error handling is ignored by the programmer • Errors are handled by means of conditional logic

  15. Error handling without language support • We consider the following case: • Errors are signaled by unusual return values • They are handled by conditional logic • Problem: No separation of normal code from error handling • Suppose we had a function that reads a whole file from hard disk into memory (in pseudo code): readFile { open the file; determine its size; allocate that much memory; read the file into memory; close the file; }

  16. Error handling without language support • The function seems simple at first sight… • But it ignores all possible errors: • File cannot be opened • Length of file cannot be determined • Not enough space in memory to read the file • Reading from the file fails • File cannot be closed • Including appropriate error handling may result in serious code bloat, as seen on the next slide

  17. Error handling without language support errorCodeType readFile { initialize errorCode = 0; open the file; if (theFileIsOpen) { determine the length of the file; if (gotTheFileLength) { allocate that much memory; if (gotEnoughMemory) { read the file into memory; if (readFailed) { errorCode = -1; } } else { errorCode = -2; } } else { errorCode = -3; } close the file; if (theFileDidNotClose && errorCode == 0) { errorCode = -4; } else { errorCode = errorCode && -4; } } else { errorCode = -5; } return errorCode; }

  18. Error handling without language support • Including error handling results in 29 instead of 7 lines of code - a factor of nearly 400%! • The main purpose of the code gets lost in the code for the discovery, signaling and treating of errors. • The logic flow of the code is hard to follow, which makes finding programming errors harder • Is the file closed in case we are out of memory? • It gets even worse if the function should be modified later!

  19. Error handling without language support • Conclusion: trade-off between reliability and readability • If errors are handled, program structure gets complex (e.g. many “if” statements) • If errors are ignored, the reliability is lost • Exception handling without language support is not feasible!

  20. Overview • Errors and their classification • Error handling without language support and its problems • Basics of error handling with language support in Java • Advantages of error handling with language support in Java • Summary

  21. Exception handling in Java • Exceptions are Java objects • The Java compiler enforces the treatment of certain types of errors • If an error occurs while executing a method: • This method [or the runtime system] creates an exception object. This object contains information about the type of the error, the state of the program at the time of the error, etc. • Exception raised: control and the created exception object are yielded to the runtime system • The runtime system looks for code that can handle the raised (thrown) exception • Candidates for providing handlers are methods in the call-chain of the method where the error occurred • The call chain is searched backwards

  22. Throwing an exception public class Car { public void start() { // … // battery might be (close to) empty // driver might not be authorized } } The battery might be (close to) empty. In order to avoid a program crash, an exception shall be thrown  BatteryLowException The driver may not be authorized for this car  Exception:SecurityException

  23. Throwing an exception public class Car { // ... public void start() { // ... if (batteryLevel <= 5) throw new BatteryLowException( "Battery is empty"); if (!driver.isAuthorized()) throw new SecurityException( "No access rights"); // start the car } } Will not be accepted by the compiler! Throw-Statement: "throw"Exception-Object. Constraint: Exception-Object must be of a subtype of type Exception (more in a minute). Almost always created in place by means of new

  24. Declaring potentially raised exceptions public class Car { public void start() throws BatteryLowException, SecurityException { // . . . // start car } } The method has to declare thrown exceptions in its signature. They belong to a method’s signature just like the return type. • Declaration syntax: "throws"<Exception-List> • <Exception-List> = <Exception-Name> • {"," <Exception-List>}. • We can declare several exceptions to be thrown • The Java compiler checks if the declaration is correct • Can exceptions occur which are not declared or will not be caught?

  25. Calling methods that raise exceptions publicclass Bar { // . . . publicvoid doSomethingWithCar(Car car) { // . . . car.start(); // . . . } } This code will not be accepted by the compiler! Reason: doSomethingWithCar calls a method that can eventually raise exceptions. These possible exceptions are ignored  Program crash!

  26. Handling raised exceptions public class Bar { public void doSomethingWithCar (Car car) { // . . . try{ car.start(); } catch(BatteryLowException bE) { // Exception handling } catch(SecurityException secEx) { // Exception handling } // . . . } } try-block signals the willingness to catch and handle exceptions that occur in statements within the block. Catching and handling the exceptions happens in catch-blocks. 1. possibility: calling method handles exceptions eventually raised by called methods

  27. Handling raised exceptions • Each catch block declares a formal parameter • Example: catch(SecurityException e) • The parameter type determines the exception type that the catch-block catches and handles • Here: SecurityException • The parameter (here: e) is a local variable in the catch-block • Allows references to the exception object to handle within the catch block • Allows access to methods and attributes of the exception object • Exceptions are ordinary Java objects, defined in ordinary Java classes • Typical method calls: • e.getMessage() – accesses the error text • e.printStackTrace() – prints out the call stack when e was created

  28. Handling several exceptions of a block How to handle the case when several exceptions are thrown by the statements of a statement block? • There can be several catch blocks for one try block! • Individual statements that potentially throw several exceptions are also put in a try block. • The first appropriate catch block will be executed • Attention should be paid when exceptions are in an inheritance hierarchy (more in a minute)!

  29. Propagating errors in Java public class Bar { public void doSomethingWithCar (Car car) throws BatteryLowException, SecurityException { // . . . car.start(); // . . . } } 2. possibility: Calling method further throws exceptions potentially raised by called methods along the call chain

  30. main start() o2.doSmthWithCar() Propagating errors in Java public class Client { public static void main(String[] args) { // ... Car car = ...; Bar o2 = new Bar(); o2.doSomethingWithCar(car); // ... } } :Client o2: Bar :Car Look up the first method with a catch-block for the raised exception and continue with that code. If none is found, the program ends with an error message. 30

  31. Ensuring execution of certain actions How can one ensure that certain actions are always executed? • Problem: In programs with exceptions, there are several possibilities to exit the program. • Sometimes the execution of certain actions must be guaranteed, no matter whether an exception occurred or not • Example: Writing to a successfully opened file • The file should always be closed, whether the data was written or not.

  32. Der finally-Block Code duplication public void test() { Switch sw = new Switch(); try { sw.on(); // code that may throw exceptions sw.off(); } catch (BatteryLowException ebEx) { sw.off(); // don’t do this; it duplicates code System.err.println("Caught BatteryLowException"); } catch (SecurityException secEx) { sw.off(); // don’t do this; it duplicates code System.err.println("Caught SecurityException"); } }

  33. Ensuring execution of certain actions • Java provides a finallyblock • The statements within the finallyblocks are always executed • After finishing the try blocks if no exception has occurred • After finishing the catchblocks if an exception was thrown public void test() { Switch sw = new Switch(); try { sw.on(); // code that may throw exceptions } catch (BatteryLowException ebEx) { // ... } catch (SecurityException secEx) { // ... } finally { sw.off(); } } sw is turned off independent of the concrete control flow of the program

  34. Advantages of the finally block • The statements within the finally block are executed independent of exception occurrence • There is no duplicated code, which must be executed whether there is an exception or not. • Attention: • Statements in the finally block can also throw exceptions! • Closing files or network connections fails, NullPointerException, ... • Handling the exceptions in finally blocks is done in the same way as in any other block...

  35. Overview • Errors and their classification • Error handling without language support and its problems • Basics of error handling with language support in Java • Advantages of error handling with language support in Java • Summary

  36. Advantages of error handlingwith language support • Separation of the error handling from “normal” logic • Propagation of errors along the dynamic call chain • Distinction and grouping of different types of errors • Compiler ensures that certain types of errors get handled

  37. 1. Separation of error handling • Java’s exception handling constructs enable separation of normal code and error handling • Attention!Separation of exception handling does not save the work of discovering, signaling and recovering from errors • The separation is the advantage! void readFile() { try { open the file; determine its size; allocate that much memory; read the file into memory; close the file; } catch (FileOpenFailed) { doSomething; } catch (sizeDeterminationFailed) { doSomething; } catch (memoryAllocationFailed) { doSomething; } catch (readFailed) { doSomething; } catch (fileCloseFailed) { doSomething; } }

  38. 2. Propagation of exceptions • Suppose readFile is the fourth method in a call chain: method1, method2, method3, readFile • Suppose method1 is the only method interested in handling errors occurring in readFile • Without language support for exceptions, method2 and method3 must propagate the error codes of readFile until they reach method1. method3 { call readFile; } method1 { call method2; } method2 { call method3; }

  39. 2. Propagation of exceptions method1{ errorCodeType error; error = call method2; if(error) doErrorProcessing; else proceed; } errorCodeType method2 { errorCodeType error; error = call method3; if (error) return error; else proceed; } errorCodeType method3{ errorCodeType error; error= call readFile; if (error) return error; else proceed; }

  40. 2. Propagation of exceptions • In contrast to this, the runtime system of Java automatically searches backwards through the call chain for methods that can handle the exceptions method1 { try { call method2; } catch(exception) { doErrorProcessing; } } method2 throws exception { call method3; } method3 throws exception { call readFile; }

  41. 3. Java’s exception type hierarchy • All exception types in Java inherit from the predefined class java.lang.Throwable "hard" VM failures; should not be caught by a program can be ignored; need not be declared or handled can be extended by programmer

  42. The class Throwable creates a Throwable object with an error description Throwable Throwable() Throwable(String) getMessage(): String printStackTrace() printStackTrace(PrintStream) ... returns theerror description prints the call stack at the time during the execution when the Throwable object was created

  43. Methods of class Exception public class ExceptionMethods { public static void main(String[] args) { try { throw new Exception("Here’s my Exception"); } catch (Exception e) { System.out.println("Caught exception"); System.out.println("e.getMessage(): "+e.getMessage()); System.out.println("e.toString(): "+e.toString()); System.out.println("e.printStackTrace():"); e.printStackTrace(); } } }

  44. Serious Exceptions: Error • It does not make sense to handle errors • Handling them is not enforced by the compiler. • Will often lead to program crash • Program cannot continue, e.g., out of memory

  45. Unchecked exceptions: RuntimeException • Runtime exceptions are errors that can occur everywhere in the program, depending on run-time conditions: • Trying to call an operation on a variable with a null-reference, Violation of array boundaries… These errors can be, but do not have to be handled

  46. Unchecked exceptions: RuntimeException • Enforcing the programmer to handle run-time exceptions would render a program unreadable • Such errors can occur everywhere… • To handle NullPointerException, a catch block would be needed for every function call: • Even if the programmer is sure that each variable in the program contains a valid object! • The Compiler can not test this statically • The compiler cannot check this statically public static void main(String[] args) { // possibly ArrayIndexOutOfBoundsException, // NumberFormatException Double doubleValue = Double.parseDouble(args[0]); //possibly ArrayIndexOutOfBoundsException, // NumberFormatException Integer intValue = Integer.parseInt(args[1]); }

  47. Checked exceptions • Checked exceptions are all exception types that inherit from Exceptionbut not from RuntimeException • Several predefined classes • FileNotFoundException • IOException • … • Application specific exceptions: Defined by the programmer as (in)direct heirs of Exception.

  48. Checked exceptions • For certain exceptions the compiler enforces that checked exceptions are handled • A method must either • catch checked exceptions occurring in its scope, or • Pass the exceptions along the call chain and declare them with a throws-clause The scope of a method M is not only its own code, but also code of methods it calls. This definition is recursive.

  49. Grouping exceptions • Exceptions are ordinary Java objects defined in ordinary Java classes and have their own inheritance hierarchy • As such, one can define specialization / generalization relations between different exception types • An IndexOutOfBoundsException is thrown if an index is out of scope • ArrayIndexOutOfBoundsException is a subclass that applies to array accesses • “Out of scope”: index is negative or greater than or equal to the array size • The programmer of a method can choose to handle more or less specific exceptions.

  50. Grouping exceptions This version ofop1handles different array exceptions differently. public voidop1() { // ... catch (ArayIndexOutOfBoundsException invInd) { // do something with invInd } catch (NullPointerException npe) { // do something with npe } catch (NoSuchElementException eType) { // do something with eType } } public void op1() { // ... catch (RuntimeException e) { // do something with e } } Here all array exceptions are treated uniformly.

More Related