Phase 4
Exception Handling & Resilience Architecture
📂 Module 1_ Problem Solving & Java programming \\ 02_ExceptionHandling_Demos
4.1 Throwable Hierarchy: Checked vs Unchecked Exceptions
📖 Cay S. Horstmann • Core Java Volume I — Chapter 7, Section 7.1 ("Dealing with Errors")
“In Java, an exception object is always an instance of a class derived from Throwable. Checked exceptions represent situations beyond the program's control that the compiler forces you to handle.”
- Try-With-ResourcesAny AutoCloseable resource closes automatically in reverse order of declaration.
⚡ Pro-Tip: The finally Execution Guarantee
The finally block runs ALWAYS, even after a return statement in try! The only exception is System.exit(0) terminating the JVM process.
💡 Real-World Analogy: Airport Passport Check vs Tripping on your Shoelace
• Checked Exception (Airport Passport Check): You KNOW beforehand that traveling abroad requires a passport, and the border might deny entry. The law (compiler) forces you to have a contingency plan before boarding: you MUST write
• Unchecked Exception (Tripping on your Shoelace): You don't carry a medical emergency team with you everywhere you walk! Tripping on your shoelace (
• Error (The Airport Runway has an Earthquake):
try-catch or declare throws IOException.
• Unchecked Exception (Tripping on your Shoelace): You don't carry a medical emergency team with you everywhere you walk! Tripping on your shoelace (
NullPointerException, ArrayIndexOutOfBoundsException) is simply a careless bug in your code — tie your shoelaces! Fix your code logic instead of littering try-catch blocks everywhere.
• Error (The Airport Runway has an Earthquake):
OutOfMemoryError, StackOverflowError. Fatal, unrecoverable system catastrophes. Applications should not attempt to catch these.
🖊 Architectural Diagram: Java Throwable Class Hierarchy [Core Java Vol I Ch 7]
Mermaid Diagram
graph TD
Throwable["java.lang.Throwable"]
Throwable --> Error["java.lang.Error (Fatal System Disasters)"]
Throwable --> Exception["java.lang.Exception (Application Conditions)"]
Error --> OOM["OutOfMemoryError"]
Error --> SOF["StackOverflowError"]
Exception --> Checked["Checked Exceptions (Compiler Enforced)
IOException, SQLException"] Exception --> RuntimeException["RuntimeException (Unchecked Bugs)
NullPointerException, IndexOutOfBounds"]
IOException, SQLException"] Exception --> RuntimeException["RuntimeException (Unchecked Bugs)
NullPointerException, IndexOutOfBounds"]
📂 Module 1.../TryWithResourcesDemo.java — Modern Resource Management
import java.io.*;
public class TryWithResourcesDemo {
public static void main(String[] args) {
// Try-With-Resources (Java 7+): Any AutoCloseable resource declared in parentheses
// is GUARANTEED to be closed automatically in reverse order, even if exceptions occur!
try (BufferedReader reader = new BufferedReader(new FileReader("orders.txt"))) {
String line = reader.readLine();
System.out.println("Read: " + line);
} catch (FileNotFoundException e) {
System.err.println("Orders file missing: " + e.getMessage());
} catch (IOException e) {
System.err.println("I/O error during read: " + e.getMessage());
}
// No finally block needed! No manual reader.close() calls! No leak potential!
}
}
👁 Try-with-Resources & AutoCloseable Lifecycle Breakdown
-
AutoCloseable Interface
Any object declared inside
try (...)must implementjava.lang.AutoCloseable(orCloseable). When execution leaves the try block, the JVM automatically invokesclose()on each declared resource. -
Reverse Order Closure
If multiple resources are opened (e.g.
try (Connection c = ...; PreparedStatement p = ...; ResultSet rs = ...)), the JVM closes them in strictly reverse order of declaration (rsfirst, thenp, thenc), matching optimal cleanup semantics. -
Suppressed Exceptions
If an exception occurs inside the try block AND another exception occurs while closing the resource, Java 7+ attaches the close exception as a Suppressed Exception (accessible via
e.getSuppressed()). In classic Java 6finallyblocks, closing exceptions would overwrite and swallow the primary business exception!
📂 StringBuilderPerformanceDemo.java — Mutability & Concatenation Performance
public class StringBuilderPerformanceDemo {
public static void main(String[] args) {
// Anti-pattern: String concatenation inside loops creates 5000 garbage objects on Heap!
long start = System.currentTimeMillis();
String str = "";
for (int i = 0; i < 5000; i++) {
str += i; // SLOW: Mints 5000 separate String objects!
}
long stringTime = System.currentTimeMillis() - start;
// Best Practice: StringBuilder mutates an internal dynamic array in-place!
start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 5000; i++) {
sb.append(i); // FAST: In-place buffer expansion, 0 garbage objects!
}
long sbTime = System.currentTimeMillis() - start;
System.out.println("String loop time: " + stringTime + "ms | StringBuilder time: " + sbTime + "ms");
}
}
👁 String vs StringBuilder vs StringBuffer Performance Analysis
-
String (Immutable O(N^2))
In a loop of 5,000 iterations,
str += icreates 5,000 intermediateStringobjects and copies character arrays repeatedly. This floods the JVM Young Generation and triggers heavy Garbage Collection pauses. -
StringBuilder (Mutable O(N))
Maintains an internal resizable
char[](orbyte[]in Java 9+ Compact Strings). Callingappend()writes into the existing buffer. When capacity fills, it doubles the buffer size (amortized O(1)). Executes 100x to 1000x faster than String concatenation in loops! -
StringBuffer (Thread-Safe Legacy)
Identical to
StringBuilder, except every method is markedsynchronized. UseStringBuilderfor local method variables (99.9% of use cases). Only useStringBufferif multiple threads are appending to the same buffer concurrently.
📂 TextBlocksDemo.java — Java 15+ Multiline Text Blocks
public class TextBlocksDemo {
public static void main(String[] args) {
// Java 15+ Text Blocks: Clean multiline strings without messy \\n or \\" escaping
String jsonPayload = """
{
"employeeId": 101,
"role": "SENIOR_BACKEND_ENGINEER",
"department": "ARCHITECTURE"
}
""";
System.out.println(jsonPayload);
}
}
👁 Java 15+ Text Blocks Mechanics
-
Triple Double-Quote ("""
Opens and closes a multiline string. The opening
"""must be followed immediately by a newline — you cannot place content on the same line as the opening delimiter. -
Incidental Whitespace Stripping
The compiler automatically strips leading indentation that aligns with the closing
""". You don't have to left-align JSON or SQL code to the edge of the source file; your code stays neatly indented. -
Escape Sequences
Within text blocks, double quotes (
") do not need escaping! Ideal for SQL queries, JSON payloads, HTML templates, and XML schemas in backend microservices.
📂 ExceptionHandlingCompleteDemo.java — Multi-Catch & Chaining
import java.io.*;
import java.sql.SQLException;
public class ExceptionHandlingCompleteDemo {
static class OrderProcessingException extends Exception {
public OrderProcessingException(String message, Throwable cause) {
super(message, cause); // Exception Chaining preserves original stack trace!
}
}
public static void processOrder(String file) throws OrderProcessingException {
try {
if (file == null) throw new FileNotFoundException("File path is null");
if (file.equals("db_error")) throw new SQLException("Connection timed out");
} catch (FileNotFoundException | SQLException e) {
// Multi-catch (Java 7+): catches related exceptions using pipe '|' operator
// Wrap and rethrow as high-level domain exception while preserving cause:
throw new OrderProcessingException("Failed to process order file: " + file, e);
}
}
public static void main(String[] args) {
try {
processOrder("db_error");
} catch (OrderProcessingException e) {
System.err.println("Caught Domain Error: " + e.getMessage());
System.err.println("Root Cause: " + e.getCause());
}
}
}
👁 Multi-Catch, Exception Chaining & Custom Exceptions Explained
-
Custom Domain Exception
Lines 3-7:
OrderProcessingException extends Exceptioncreates a checked application exception. In clean backend architecture, low-level technical errors (SQL syntax, network drops) are wrapped into meaningful domain exceptions. -
Exception Chaining (super(msg, cause))
Line 5: Passing
cause(the originalSQLException) tosuper(message, cause)ensures the original stack trace is NOT lost! When viewing logs in Kibana or Datadog, developers can inspect the full root cause chain viae.getCause(). -
Multi-Catch Pipe Operator (|)
Line 13:
catch (FileNotFoundException | SQLException e)— Eliminates duplicate error handling logic. Rule: In a multi-catch statement, parametereis implicitlyfinal, and the caught exceptions cannot have an inheritance relationship (e.g. you cannot writecatch (IOException | FileNotFoundException e)becauseFileNotFoundExceptionis already anIOException).
📂 Module 1.../02_ExceptionHandling_Demos/.../InvalidCredentialsException.java & User.java
package com.accenture.ltt.exceptions.customexceptions.solutions;
// 1. Custom Checked Exception: Extends java.lang.Exception
public class InvalidCredentialsException extends Exception {
private static final long serialVersionUID = 1L;
public InvalidCredentialsException() { super(); }
public InvalidCredentialsException(String message) { super(message); }
}
// 2. Service Class throwing Custom Exception
class User {
String username;
String password;
public void validate() throws InvalidCredentialsException {
if ("admin".equals(username) && "pass@123".equals(password)) {
System.out.println("Authentication successful!");
} else {
// Throw custom exception enforcing business rules
throw new InvalidCredentialsException("Username or password is invalid.");
}
}
}
👁 Custom Checked Exception Design Breakdown
-
Extending Exception
Extending
java.lang.Exceptioncreates a checked exception, forcing calling code to explicitly handle or declare it withthrows. (ExtendingRuntimeExceptionwould create an unchecked exception). -
Passing Message to super
Line 8:
super(message)passes the descriptive error text up toThrowable, making it viewable viae.getMessage()and printed in log stack traces.
📂 Module 1.../02_ExceptionHandling_Demos/.../FinallyClause.java
package com.accenture.ltt.exceptions.runtime;
import java.util.InputMismatchException;
import java.util.Scanner;
public class FinallyClause {
public static void division() {
Scanner sc = new Scanner(System.in);
try {
System.out.println("Enter a and b: ");
int a = sc.nextInt();
int b = sc.nextInt();
int c = a / b;
System.out.println("Result: " + c);
} catch (InputMismatchException | ArithmeticException e) {
System.err.println("Handled exception: " + e.getClass().getSimpleName());
} finally {
// GUARANTEED to execute: Even if exceptions occur or return is executed!
System.out.println("finally block executed: Cleaning up resources...");
sc.close();
}
}
}
👁 The finally Execution Guarantee & Edge Cases
-
Execution Guarantee
The
finallyblock executes whether an exception was thrown or not, whether it was caught or not, and even if areturnstatement is executed inside thetryblock! -
Only 2 Ways finally Doesn't Run
(1)
System.exit(0)terminates the JVM process immediately. (2) Fatal hardware or OS crash (power outage or kernel panic).