Java Fundamentals

Exception Handling

Prepared by Srikanth Mamillapalli

1. Exception Handling

An exception is an unexpected unwanted event that disturbs the normal flow of a program.

Examples

Tyre puncture, sleeping exception, file-not-found exception.

Main Objective

Provide an alternate way to continue the rest of the program normally and achieve graceful termination.

Example from the source: If a remote file located in London is unavailable at runtime, the program can use a local file and continue normally.
try {
    // Read data from London file
} catch (FileNotFoundException ex) {
    // Use local file and continue normally
}

2. Runtime Stack Mechanism

For every thread, the JVM creates a runtime stack. Every method call made by that thread is stored in the corresponding stack.

  • Each entry is called a Stack Frame or Activation Record.
  • After a method completes, its stack-frame entry is removed.
  • After all method calls complete, the stack becomes empty and is destroyed by the JVM before the thread terminates.
main()
  └── doStuff()
        └── doMoreStuff()
Source diagram: The PDF page 2 illustrates the runtime stack for the main thread and shows the three stack frames.

3. Default Exception Handling in Java

When an exception occurs inside a method, the method creates an exception object containing the exception name, description and location/stack trace, then hands the object to the JVM.

  1. The JVM checks whether the current method contains exception-handling code.
  2. If not, the method terminates abnormally and its stack frame is removed.
  3. The JVM checks the caller method and continues this process up to main().
  4. If no handler is found, the JVM passes responsibility to the Default Exception Handler.
  5. The default handler prints exception information and terminates the program abnormally.
Exception in thread "main"
ExceptionName: description
    at ClassName.method(ClassName.java:line)
    at ClassName.main(ClassName.java:line)
Important: If at least one method terminates abnormally, the program termination is abnormal. Normal termination occurs only when all methods terminate normally.

4. Exception Hierarchy

The Throwable class acts as the root of the Java exception hierarchy and defines two major child classes: Exception and Error.

Exception

Most exceptions are caused by the program and are recoverable. For example, a missing remote file can be handled by using a local file.

Error

Errors are generally associated with lack of system resources and are not normally recoverable by application code, such as OutOfMemoryError.

Throwable
├── Exception
│   └── RuntimeException
└── Error

Examples Mentioned in the Source

CategoryExamples
Runtime exceptionsArithmeticException, NullPointerException, ClassCastException, ArrayIndexOutOfBoundsException, StringIndexOutOfBoundsException, IllegalArgumentException, NumberFormatException
ErrorsVM Error, StackOverflowError, OutOfMemoryError, AssertionError, ExceptionInInitializerError
I/O exceptionsEOFException, FileNotFoundException

5. Checked and Unchecked Exceptions

The source describes checked exceptions as exceptions checked by the compiler for smooth runtime execution. If a checked exception can be raised, it must be handled using try/catch or declared with throws; otherwise a compile-time error occurs.

Unchecked exceptions are not checked by the compiler for handling. Examples include ArithmeticException, NullPointerException, ClassCastException, array/string index exceptions, IllegalArgumentException and NumberFormatException.

TypeExamples from the source
CheckedIOException, InterruptedException, FileNotFoundException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException
UncheckedRuntimeException and its child classes; Error and its child classes
Source note: Every exception occurs at runtime; the distinction is whether the compiler requires the programmer to handle/declare it.

Fully Checked vs Partially Checked

TypeMeaningExamples
Fully checkedAll child classes are also checked.IOException, InterruptedException
Partially checkedSome child classes are unchecked.Exception, Throwable

6. Exception Handlers: try and catch

The source calls code that may raise an exception risky code. Risky code is placed inside a try block, while corresponding handling code is placed inside a catch block.

try {
    // risky code
} catch (Exception ex) {
    // handle code
}
Good practice: Keep only risky code inside the try block and keep the try block as small as possible.

7. Control Flow in try/catch

Case Studies

SituationExecutionResult
No exception1 → 2 → 3 → 5Normal termination
Exception at statement 2 and catch matches1 → 4 → 5Normal termination
Exception at statement 2 and catch does not match1Abnormal termination
Exception at statement 1 and catch does not matchAbnormal terminationAbnormal termination
Exception at statement 51 → 2 → 3Abnormal termination
  • Once an exception occurs anywhere in a try block, the remaining statements in that try block are not executed, even if the exception is handled.
  • An exception can also occur inside a catch or finally block.
  • An exception raised outside a try block always causes abnormal termination unless handled elsewhere by normal propagation.

8. Printing Exception Information

MethodPrintable information
printStackTrace()Exception name, description and stack trace
toString()Exception name and description
getMessage()Description/message

Throwable

Provides printStackTrace(), toString() and getMessage().

9. Multiple catch Blocks

The source recommends a separate catch block for each exception type when the handling differs between exception types.

try {
    BufferedReader br =
        new BufferedReader(new FileReader("abc.txt"));
} catch (ArithmeticException ex) {
    // handling code
} catch (FileNotFoundException ex) {
    // handling code
} catch (NullPointerException ex) {
    // handling code
} catch (Exception ex) {
    // handling code
}
Catch order matters: place the child exception before its parent. Otherwise the later catch block becomes unreachable and causes a compile-time error.

10. finally Block

The finally block is the recommended place for cleanup code that should execute regardless of whether an exception is raised or handled.

  • Cleanup code should not depend on the try block completing every statement.
  • Cleanup code should not be placed only in catch because catch does not execute when there is no exception.
  • The finally block normally executes whether an exception occurs or not, and whether it is handled or not.
  • If a return statement occurs in try/catch, finally executes before the return is completed.
try {
    // risky code
} catch (Exception ex) {
    // handle code
} finally {
    // cleanup code
}
Special case from the source: System.exit(0) shuts down the JVM, so finally is not executed in that case.

11. throw and throws

throw

The throw keyword is used to explicitly create/hand over an exception object to the JVM. The source highlights user-defined/custom exceptions as an important use case.

throw new ArithmeticException("/ by zero");
  • After a throw statement, statements written immediately after it are unreachable.
  • The thrown object must be a Throwable type.
  • Throwing a null reference results in a NullPointerException.

throws

The throws keyword delegates exception-handling responsibility to the caller.

public void readFile() throws FileNotFoundException {
    // code that may raise the exception
}
throwthrows
Used to explicitly throw an exception object.Used to declare/delegate exception-handling responsibility.
Used inside method/block logic.Used in a method or constructor declaration.
Works with Throwable objects.Declares Throwable types.
Source guidance: throws is mainly required for checked exceptions; the notes recommend try/catch over throws when practical.

12. Top Exceptions and Who Raises Them

The source divides exceptions/errors based on who raises them into JVM Exceptions and Programmatic Exceptions.

Exception / ErrorRaised bySource description
AIOBJVMArray index is outside the valid range.
NPEJVMAn operation is performed on null.
CCEJVMInvalid casting from parent/object type to child type.
ArithmeticExceptionJVMRaised automatically for arithmetic problems such as division by zero.
StackOverflowErrorJVMCan occur during excessive recursive method calls.
NoClassDefFoundErrorJVMClass definition cannot be found at runtime.
ExceptionInInitializerErrorJVMOccurs while executing static initialization.
IllegalArgumentExceptionProgrammer/APIMethod invoked with an illegal argument.
NumberFormatExceptionProgrammer/APIString-to-number conversion is attempted with an improperly formatted string.
IllegalStateExceptionProgrammer/APIMethod is invoked at an inappropriate time/state.
AssertionErrorProgrammer/APIAn assert statement fails.

13. Java 7 Exception Handling Enhancements

Try-with-resources

Resources opened in the try block are closed automatically when control reaches the end of the try block, normally or abnormally.

Multi-catch

A single catch block can handle multiple different exception types.

Try-with-resources

  • Reduces the need for explicit cleanup and reduces code length.
  • Multiple resources can be declared using semicolons.
  • Resources must be auto-closable.
  • A resource is auto-closable when its class implements java.lang.AutoCloseable.
  • I/O, database and network-related resources commonly implement this interface.
  • AutoCloseable was introduced in Java 7 and contains close().
  • Resource reference variables are implicitly final within the try block, so reassignment is not allowed.
  • From Java 7, try-with-resources can be used without an explicit catch/finally block.
try (R1 r1 = ...; R2 r2 = ...; R3 r3 = ...) {
    // use resources
}

Multi-catch

try {
    // risky code
} catch (IOException | SQLException ex) {
    // common handling code
}
Restriction: Exception types in a multi-catch alternative cannot have a parent-child relationship or otherwise be related by subclassing.

14. Exception Propagation and Re-throwing

Exception Propagation

If an exception is raised inside a method and is not handled there, the exception object is propagated to the caller method. The caller becomes responsible for handling it.

Method A
Method B
Caller / JVM

Re-throwing Exception

The source describes re-throwing as an approach that can be used to convert one exception into another exception type.

15. User-Defined Exceptions

If a programmer implements their own exception, it is called a user-defined exception.

The source states that a user-defined exception class should extend one of the following:

  • Exception
  • RuntimeException
  • Throwable
class MyException extends Exception {
    public MyException(String message) {
        super(message);
    }
}

16. Examples from the Source PDF

The later pages of the PDF contain practical exception examples, program output and exception traces. These pages are preserved below as page images so the original code screenshots, console output and diagrams remain available.

Example visible in the source: a ClassCastException stack trace showing an invalid cast from java.lang.Object to java.lang.String.

17. Quick Revision

TopicKey point
ExceptionUnexpected event that disturbs normal program flow.
ThrowableRoot class of the exception hierarchy.
tryContains risky code.
catchContains exception-handling code.
finallyUsed mainly for cleanup code.
throwExplicitly throws an exception object.
throwsDeclares/delegates exception-handling responsibility.
Checked exceptionCompiler requires handling or declaration.
Unchecked exceptionCompiler does not require explicit handling.
Try-with-resourcesAutomatically closes AutoCloseable resources.
Multi-catchOne catch block handles multiple unrelated exception types.
PropagationUnhandled exception moves to the caller.
User-defined exceptionCustom exception implemented by the programmer.