Question 3 · Section 7

What is an unchecked exception (Runtime Exception)?

Basic unchecked exceptions (NPE, IllegalArgumentException) signal bugs. However, domain unchecked exceptions (UserNotFoundException, OrderAlreadyExistsException) are expected bu...

Language versions: English Russian Ukrainian

Junior Level

Definition

Unchecked exceptions are exceptions that inherit from RuntimeException. The compiler does not require handling them.

Hierarchy

Throwable
  └── Exception
        └── RuntimeException  <- unchecked
              ├── NullPointerException
              ├── IllegalArgumentException
              ├── IndexOutOfBoundsException
              ├── ArithmeticException
              └── ClassCastException

Examples

// NullPointerException - most common
String s = null;
s.length(); // NPE

// IllegalArgumentException
public void setAge(int age) {
    if (age < 0) throw new IllegalArgumentException("Age must be positive");
}

// ArithmeticException
int x = 10 / 0; // ArithmeticException

When they occur

  • Programming errors (null, wrong arguments)
  • Violation of method contracts
  • Logic errors in code

Should you handle them?

Basic unchecked exceptions (NPE, IllegalArgumentException) signal bugs. However, domain unchecked exceptions (UserNotFoundException, OrderAlreadyExistsException) are expected business situations, not bugs.


Middle Level

When NOT to use unchecked exceptions

  1. Public libraries for third-party developers - checked exceptions enforce useful handling
  2. Team without error handling culture - checked = insurance against forgetfulness
  3. Critical systems - if ignoring an error = financial loss, checked will force handling

Under the Hood: fillInStackTrace()

The main “cost” of an exception is the native method fillInStackTrace(), which walks the thread’s stack. In high-load systems (100k+ RPS), generating exceptions can consume 20-30% of CPU.

Fail-Fast Principle

Fail-Fast - principle: an error should manifest as early as possible, not “leak” through 10 layers of code. NPE on line s.length() instantly points to the problem, rather than “surfacing” after an hour of operation.

Unchecked exceptions are ideal for implementing Fail-Fast:

public User findUser(Long id) {
    Objects.requireNonNull(id, "ID cannot be null");
    // If null - fail immediately, not 10 layers deep
    return repository.findById(id)
        .orElseThrow(() -> new UserNotFoundException("User not found: " + id));
}

Centralized handling

In Spring Boot, use @ControllerAdvice + @ExceptionHandler:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(UserNotFoundException e) {
        return ResponseEntity.status(404)
            .body(new ErrorResponse("USER_NOT_FOUND", e.getMessage()));
    }

    @ExceptionHandler(ValidationException.class)
    public ResponseEntity<ErrorResponse> handleValidation(ValidationException e) {
        return ResponseEntity.status(400)
            .body(new ErrorResponse("VALIDATION_ERROR", e.getMessage()));
    }
}
// Flow: Exception "bubbles up" through all service layers ->
// Spring finds @ExceptionHandler with matching type ->
// Calls method -> ResponseEntity becomes JSON response.

Why Spring chose unchecked

  1. Code cleanliness - no try-catch noise
  2. Centralized handling - all errors bubble up to @ControllerAdvice
  3. Reactive programming - in Project Reactor, checked exceptions are practically impossible

Senior Level

Performance and optimization

Pre-instantiated Exceptions - for frequently occurring errors, you can create a singleton exception without stack trace:

public static final ValidationException INVALID_FORMAT =
    new ValidationException("Invalid format", null, false, false);

This exception does not create GC load, but makes debugging harder (no stack trace).

Control Flow Anti-pattern

Never use exceptions for control flow:

// BAD - slow and unreadable
try {
    User user = findUser(id);
} catch (UserNotFoundException e) {
    // transition to next step
}

// GOOD
Optional<User> user = findUser(id);
if (user.isPresent()) { ... }

Returning Optional is 100-1000x faster than throwing an exception.

Error vs RuntimeException

Don’t confuse them:

  • Error - JVM problems (OutOfMemoryError, StackOverflowError). Catching is bad practice
  • RuntimeException - application errors. Handle centrally

Swallowing Exceptions

The worst crime:

catch (RuntimeException e) { } // Silently swallows the bug

Diagnostics and monitoring

  • Micrometer - count RuntimeExceptions. A sharp rise in NPE is reason to rollback a deployment
  • Log Enrichment - log context (userId, orderId), not just the stack trace
  • Metric-driven Exception Tracking - alerting on anomalies in exceptions

Interview Cheat Sheet

Must know:

  • Unchecked exceptions inherit from RuntimeException, compiler does not require handling
  • Basic unchecked (NPE, IllegalArgumentException) signal bugs; domain (UserNotFoundException) - business situations
  • Fail-Fast - error should manifest as early as possible
  • Spring Boot handles unchecked centrally via @ControllerAdvice + @ExceptionHandler
  • fillInStackTrace() - most expensive part, can consume 20-30% of CPU at 100k+ RPS
  • Pre-instantiated exceptions (singletons) reduce GC load
  • Never use exceptions for control flow - Optional is 100-1000x faster
  • Swallowing exceptions (catch (RuntimeException e) {}) - the worst crime

Frequent follow-up questions:

  • Why does Spring prefer unchecked exceptions? - Code cleanliness, centralized handling via @ControllerAdvice, compatibility with Reactive programming
  • When are unchecked exceptions NOT recommended? - Public libraries, teams without error handling culture, critical financial systems
  • How to speed up creation of frequent exceptions? - Pre-instantiated exceptions with writableStackTrace = false
  • How does Error differ from RuntimeException? - Error - JVM problems (don’t catch), RuntimeException - application errors (handle centrally)

Red flags (NOT to say):

  • “I use exceptions for business logic control flow” - this is an anti-pattern, slow and unreadable
  • “Unchecked exceptions don’t need to be handled at all” - they do, but centrally
  • “Silently swallowing RuntimeException is normal practice” - it hides bugs

Related topics:

  • [[What is the difference between checked and unchecked exceptions]]
  • [[What is a checked exception and when to use it]]
  • [[What is the difference between Error and Exception]]
  • [[What is a stack trace]]
  • [[How to properly log exceptions]]