Error vs Exception - Yash-777/MyWorld GitHub Wiki

public class Throwable implements Serializable gitlink

Diagram Exception Hierarchy
An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.
Throwable
β”œβ”€β”€ Error (unchecked)
β”‚   β”œβ”€β”€ OutOfMemoryError
β”‚   β”œβ”€β”€ StackOverflowError
β”‚   β”œβ”€β”€ java.lang.Error: Unresolved compilation problem
β”‚   └── ...
└── Exception
    β”œβ”€β”€ RuntimeException (unchecked) - No compile-time error
    β”‚   β”œβ”€β”€ NullPointerException
    β”‚   β”œβ”€β”€ ArrayIndexOutOfBoundsException
    β”‚   β”œβ”€β”€ IllegalArgumentException
    β”‚   └── ...
    └── Checked Exceptions - Must be handled (try-catch or throws)
        β”œβ”€β”€ IOException
        β”œβ”€β”€ SQLException
        β”œβ”€β”€ ClassNotFoundException
        └── ...
      
Error Checked Exceptions Un-Checked Exceptions (RuntimeException)
No compile-time error
public static void triggerUnrecoverableError() {
    System.out.println("Method: Throwing a System Error.");
    throw new Error("Critical Failure: The system cannot continue.");
}
public static void causeError() {
    System.out.println("Throwing Error...");
    throw new StackOverflowError("Serious JVM Error");
}
public static void demonstrateErrorWithThrows() throws Error {
    System.out.println("Method: Error with throws declaration");
    throw new Error("Critical system error");
}
public static void demonstrateErrorNoThrows() {
    System.out.println("Method: Error without throws (not required)");
    throw new Error("Critical system error");
}
public static void causeCheckedException() throws MyCheckedException {
    System.out.println("Throwing Checked Exception...");
    throw new MyCheckedException("Custom Checked Exception Occurred");
}
public static void demonstrateCheckedExceptionWithThrows() throws MyCheckedException {
    System.out.println("Method: Checked exception with throws declaration");
    throw new MyCheckedException("Custom checked exception");
}
Custom Checked Exception - Class
class MyCheckedException extends Exception {
    public MyCheckedException(String message) {
        super(message);
    }
}
public static void demonstrateUncheckedExceptionNoHandling() {
    System.out.println("Method: RuntimeException without handling");
    throw new RuntimeException("Runtime error occurred");
}
public static void demonstrateUncheckedExceptionWithTryCatch() {
    System.out.println("Method: RuntimeException with try-catch");
    try {
        throw new RuntimeException("Runtime error occurred");
    } catch (RuntimeException e) {
        System.out.println("Caught: " + e.getMessage());
    }
    System.out.println("Execution continues after catch");
}
public static int getLength(String s) {
  if (s == null) {
    System.out.println("Throwing Runtime Exception...");
    throw new IllegalArgumentException("The argument cannot be null");
  }
  return s.length();
}

Error Behavior with Threads

Error can be caught using catch, but it is not recommended.
Errors represent serious problems. You can catch them to prevent abnormal thread termination, but generally applications are not expected to recover from them.
If an Error is not caught, the current thread terminates β€” but the finally block still executes.
Even when an Error occurs, the finally block runs (unless the JVM itself crashes). After that, the current thread stops, but other threads continue running normally.
Thread Isolation: Each thread runs independently.
An Error in one thread usually affects only that particular thread, not the entire application. Other request threads keep processing.
Error CAN be caught to prevent thread termination βœ…
Result: Thread survives, continues execution
// Example 1: StackOverflowError with finally
public static void demonstrateStackOverflowErrorWithFinally() {
    System.out.println("--- StackOverflowError Test ---");
    try {
        System.out.println("Before causing StackOverflowError");
        causeStackOverflow(0);
        System.out.println("After error (won't print)");
    } catch (StackOverflowError e) {
        System.out.println("Caught StackOverflowError");
    } finally {
        System.out.println("βœ“ Finally block EXECUTED despite StackOverflowError");
    }
    System.out.println("Program continues after finally\n");
}
// Example 2: Simulated OutOfMemoryError with finally
public static void demonstrateOutOfMemoryErrorWithFinally() {
    System.out.println("--- Custom Error Test ---");
    try {
        System.out.println("Before throwing Error");
        throw new OutOfMemoryError("Simulated memory error");
    } catch (OutOfMemoryError e) {
        System.out.println("Caught OutOfMemoryError: " + e.getMessage());
    } finally {
        System.out.println("βœ“ Finally block EXECUTED despite OutOfMemoryError");
    }
    System.out.println("Program continues after finally\n");
}
      
Error with Finally (NOT caught) = Thread dies BUT finally executes βœ…
Result: Finally runs β†’ Thread terminates β†’ Other threads continue
public static void demonstrateErrorWithFinallyNoCatch() {
    System.out.println("--- Error without Catch Test ---");
    try {
        System.out.println("Before throwing Error");
        throw new Error("Generic error");
    } finally {
        System.out.println("βœ“ Finally block EXECUTED even without catch block");
    }
    // Program terminates after finally
}
      
Real Server Example (Simplified Servlet)
public class ServletRequestHandler {
    public void handleHttpRequest(HttpRequest request) {
        String threadName = Thread.currentThread().getName();
        Connection dbConnection = null;
        try {
            System.out.println("[" + threadName + "] Processing request: " + request.getUrl());

            dbConnection = getDbConnection();

            // User's buggy code might cause StackOverflowError
            String result = processUserRequest(request);

            sendResponse(result);
            
        } catch (Exception e) {
            System.err.println("[" + threadName + "] Exception: " + e.getMessage());
            sendErrorResponse(500);
        } finally {
            // βœ“ This executes even if StackOverflowError occurs
            if (dbConnection != null) {
                dbConnection.close(); // Resource cleanup happens
                System.out.println("[" + threadName + "] βœ“ DB connection closed");
            }
            System.out.println("[" + threadName + "] Request completed (thread ending)");
        }

        // If Error occurred, thread dies here but server continues
        // Other request threads keep processing
    }
}
      
Thread Isolation: Error kills ONLY that thread βœ…
Result: Thread-2 dies, Thread-1 and Thread-3 continue βœ“
Thread t1 = new Thread(() -> {
    System.out.println("Thread-1: Working...");
    // No error - completes normally
});

Thread t2 = new Thread(() -> {
    System.out.println("Thread-2: Working...");
    throw new StackOverflowError(); // Dies here
});

Thread t3 = new Thread(() -> {
    System.out.println("Thread-3: Working...");
    // No error - completes normally
});

t1.start();
t2.start(); // ← Only this thread dies
t3.start();
      
Server with Multiple Request Threads
public class ErrorThreadBehavior {
    public static void main(String[] args) {
        System.out.println("=== Server Simulation: Multiple Request Threads ===\n");

        // Simulate 5 concurrent user requests
        Thread request1 = new Thread(() -> handleRequest("User-1", false), "Request-Thread-1");
        Thread request2 = new Thread(() -> handleRequest("User-2", true),  "Request-Thread-2"); // Will throw StackOverflowError
        Thread request3 = new Thread(() -> handleRequest("User-3", false), "Request-Thread-3");
        Thread request4 = new Thread(() -> handleRequest("User-4", false), "Request-Thread-4");

        // Start all threads
        request1.start();
        request2.start();
        request3.start();
        request4.start();

        // Main thread continues
        System.out.println("[MAIN] Server main thread continues running...\n");

        // Wait for all threads to complete
        try {
            request1.join();
            request2.join(); // This will finish (abnormally)
            request3.join();
            request4.join();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("\n[MAIN] All request threads completed. Server still running!");
    }
    
    public static void handleRequest(String user, boolean causeError) {
        String threadName = Thread.currentThread().getName();
        System.out.println("[" + threadName + "] Processing request for " + user);
        try {
            Thread.sleep(100); // Simulate processing time

            if (causeError) {
                System.out.println("[" + threadName + "] Triggering StackOverflowError...");
                causeStackOverflow(); // This will kill only this thread
            }

            System.out.println("[" + threadName + "] βœ“ Successfully processed request for " + user);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // Recursive method to cause StackOverflowError
    public static void causeStackOverflow() {
        causeStackOverflow(); // Infinite recursion
    }
}

In Java, throwing exceptions is a specific programming technique. An exception can only be caught if it was thrown before, either by the Java platform (JVM) or by custom code using the throw statement.

The throw Statement - Actually Throws an Exception/Error The throws Statement - Declares Potential Exceptions/Errors
  • Purpose: Explicitly throw a Throwable object from your code
  • Syntax: throw new ExceptionType();
  • Location: Inside method body
// With Error
public void simulateCrash() {
    throw new OutOfMemoryError("Memory exhausted");
}
// With Checked Exception
public void readData() {
    throw new IOException("File not found");
}
// With Exception
public void validateAge(int age) {
    if (age < 0) {
        throw new IllegalArgumentException("Age cannot be negative");
    }
}
      
  • Purpose: Inform caller that method might throw certain exceptions
  • Syntax: returnType methodName() throws ExceptionType1, ExceptionType2
  • Location: Method signature
Key Point: throws declaration is OPTIONAL for Error (just like unchecked exceptions)
// Error - throws OPTIONAL
public void crash() throws Error { // Optional
    throw new Error("System crash");
}
// Checked Exception - throws REQUIRED
public void readFile() throws IOException {
    throw new IOException("Read error");
}
// Unchecked Exception - throws OPTIONAL
public void divide() throws ArithmeticException { // Optional
    throw new ArithmeticException("Divide by zero");
}
      

Error Class (Cannot handled by the program): When a dynamic linking failure or other hard failure in the Java virtual machine occurs, the virtual machine throws an Error. Simple programs typically do not catch or throw Errors.

Exception Class (can be handled by the program): Most programs throw and catch objects that derive from the Exception class. An Exception indicates that a problem occurred, but it is not a serious system problem. Most programs you write will throw and catch Exceptions as opposed to Errors.

What is the difference between exception and error in Java?

Errors typically happen while an application is running. For instance, Out of Memory Error occurs in case the JVM runs out of memory. On the other hand, exceptions are mainly caused by the application. For instance, Null Pointer Exception happens when an app tries to get through a null object.



Exceptions docs.oracle.com

What Is an Exception?

An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.

Java exception is an unusual condition that generally occurs in a code sequence while the program is being executed. And, when an exception occurs in your code, it completely disrupts the normal flow of the program and abnormally terminates the process, so it must be handled correctly.

The term exception is shorthand for the phrase "exceptional event."

When an error occurs within a method, the method creates an object and hands it off to the runtime system. The object, called an exception object, contains information about the error, including its type and the state of the program when the error occurred. Creating an exception object and handing it to the runtime system is called throwing an exception.

After a method throws an exception, the runtime system attempts to find something to handle it. The set of possible "somethings" to handle the exception is the ordered list of methods that had been called to get to the method where the error occurred. The list of methods is known as the call stack

image

The runtime system searches the call stack for a method that contains a block of code that can handle the exception. This block of code is called an exception handler. The search begins with the method in which the error occurred and proceeds through the call stack in the reverse order in which the methods were called. When an appropriate handler is found, the runtime system passes the exception to the handler. An exception handler is considered appropriate if the type of the exception object thrown matches the type that can be handled by the handler.

The exception handler chosen is said to catch the exception. If the runtime system exhaustively searches all the methods on the call stack without finding an appropriate exception handler, as shown in the next figure, the runtime system (and, consequently, the program) terminates.

image

Using exceptions to manage errors has some advantages over traditional error-management techniques. You can learn more in the Advantages of Exceptions section.


Exception Handling

Exception handling is the process of responding to unwanted or unexpected events when a computer program runs. Exception handling deals with these events to avoid the program or system crashing, and without this process, exceptions would disrupt the normal operation of a program.

How do you handle exceptions in Java?

Exception handling can be performed using try, catch, and finally blocks

Try blocks should include code that might throw an exception. If your code throws more than one exception, you can choose whether to:

  • Use a separate try block for every statement that may throw an exception or
  • Use one try block for several statements that could throw multiple exceptions.

Each Catch block should handle exceptions thrown by the try blocks. The finally block gets executed whether or not an exception is thrown after the successful execution of the try block or after one of the catch blocks.

There is no limit to add catch blocks, as you can include as many Catch blocks as you want. However, you can add only one finally block to each try block.

The runtime system always executes the statements within the finally block regardless of what happens within the try block. So it's the perfect place to perform cleanup.

try {

} catch (IndexOutOfBoundsException e) { // catch (ExceptionType name)
    System.err.println("IndexOutOfBoundsException: " + e.getMessage());
} catch (IOException e) {
    System.err.println("Caught IOException: " + e.getMessage());
}

Note: The finally block may not execute if the JVM exits while the try or catch code is being executed.


Types of Exceptions in Java

Generally, there are two kinds of Java exceptions, namely:

Checked exceptions (compile-time exceptions): compiler checks whether the exception is handled and throws an error accordingly. Unchecked exceptions (runtime exceptions): Occur during program execution. These are not detectable during the compilation process.

Checked exceptions. Also called compile-time exceptions, the compiler checks these exceptions during the compilation process to confirm if the exception is being handled by the programmer. If not, then a compilation error displays on the system.

The class Exception and any subclasses that are not also subclasses of RuntimeException are checked exceptions

Some of the most common Checked exceptions in Java include:

class IOException extends Exception   [CharConversionException, EOFException, FileNotFoundException, SSLException, 
ObjectStreamException, ObjectStreamException]
ParseException, InterruptedException, InvocationTargetException, NoSuchMethodException, SQLException, ClassNotFoundException.
  • IOException: Signals that an I/O exception of some sort has occurred. This class is the general class of exceptions produced by failed or interrupted I/O operations.
  • SOAPException

Unchecked exceptions. Also called runtime exceptions, these exceptions occur during program execution. These exceptions are not checked at compile time, so the programmer is responsible for handling these exceptions. Unchecked exceptions do not give compilation errors.

RuntimeException and its subclasses are unchecked exceptions. class RuntimeException extends Exception

Some of the most common Unchecked exceptions in Java include:

class ArithmeticException extends RuntimeException
class IndexOutOfBoundsException extends RuntimeException  [ArrayIndexOutOfBoundsException, StringIndexOutOfBoundsException]
NumberFormatException, ArithmeticException, ClassCastException, IllegalArgumentException, IllegalStateException
  • NullPointerException: Thrown when an application attempts to use null in a case where an object is required.
  • ArithmeticException: Thrown when an exceptional arithmetic condition has occurred. When any integet/number is "divide by zero" throws an instance of this class.
  • IndexOutOfBoundsException: Thrown to indicate that an index of some sort (such as to an array, to a string, or to a vector) is out of range.
  • ClassCastException, ConcurrentModificationException, FileSystemNotFoundException, NoSuchElementException, UnsupportedOperationException, UnmodifiableSetException, DOMException

Why do we need exception handling in Java?

If there is no try and catch block while an exception occurs, the program will terminate. Exception handling ensures the smooth running of a program without program termination.


Throwing exceptions

In Java, throwing exceptions is a specific programming technique. An exception can only be caught if it was thrown before, either by the Java platform or by custom code. In Java, exceptions are thrown with the throw statement. For example, ArrayIndexOutOfBoundsException, NullPointerException, and IOException were all thrown automatically by the Java platform.

  1. The Throw Statement

Throwable objects that inherit from the Throwable class can be used with the throw statement. Any block of code explicitly throws an exception. A catch block must follow each throw statement inside a try block.

  1. The Throws Statement

Java has a throws statement in addition to a throw. Any method that might throw a checked exception can use it in its signature. As an example, let’s say that the method doesn’t want to and cannot handle a checked exception that will prevent the code from compiling. With the throws keyword, you can indicate that the caller needs to handle this exception in its own try-catch block.


Handling NullPointerException?

NullPointerExceptionseagence.com blog is a kind of Runtime exception that occurs when you try to access a variable that doesn’t point to any object and refers to nothing or null.

Following are the most common situations for the java null pointer exception occurrence.

  • When null parameters are passed on to a method.
  • Trying to access the properties or an index element of a null object.
  • Calling methods on a null object. String str = null; str.length(); if ("Yash".equals(str))
  • Following incorrect configuration for dependency injection frameworks such as Spring.
public static int getLength(String s) {
  if (s == null)
    throw new IllegalArgumentException("The argument cannot be null");
  return s.length();
}

⚠️ **GitHub.com Fallback** ⚠️