AI InterviewSearch…Search problems, topics, or pages…Ctrl KGet started
Skip to content

12 Exceptions / Lesson 1 of 6

The exception hierarchy and how to read a stack trace

13 min · +10 XP · 2 exercises · 5 questions

Read the text13 min
Exercises0/2
Quiz5 q

Quick answer

What is the exception hierarchy in Java?

The Java exception hierarchy is rooted at Throwable, which has two branches. Error covers failures of the JVM itself, such as OutOfMemoryError, which programs should not catch. Exception covers conditions a program may handle: its subclasses are checked, so callers must catch or declare them, except RuntimeException and its subclasses, which are unchecked.

When something goes wrong at run time — an index out of range, a file missing, a null dereferenced — Java creates an exception object describing the failure and unwinds the call stack until something catches it. Every exception is an instance of a class in one hierarchy rooted at Throwable, and where a class sits in that hierarchy decides whether the compiler forces you to handle it. This lesson is the map of that hierarchy, the exceptions you will meet daily, and how to read the stack trace you get when one escapes.

The hierarchy

Throwable
├── Error                       — the JVM is in trouble; do not catch
│   ├── OutOfMemoryError
│   ├── StackOverflowError
│   ├── NoClassDefFoundError
│   └── AssertionError
└── Exception                   — something a program might recover from
    ├── IOException             — CHECKED: must be declared or caught
    │   ├── FileNotFoundException
    │   └── UncheckedIOException (RuntimeException, despite the name's neighbourhood)
    ├── SQLException             — checked
    ├── InterruptedException     — checked
    ├── ReflectiveOperationException (ClassNotFoundException, …) — checked
    └── RuntimeException         — UNCHECKED: may be thrown anywhere without declaration
        ├── NullPointerException
        ├── IllegalArgumentException
        │   └── NumberFormatException
        ├── IllegalStateException
        ├── IndexOutOfBoundsException
        │   ├── ArrayIndexOutOfBoundsException
        │   └── StringIndexOutOfBoundsException
        ├── ArithmeticException
        ├── ClassCastException
        ├── UnsupportedOperationException
        ├── ConcurrentModificationException
        ├── NoSuchElementException
        └── DateTimeException

Three tiers to remember:

  • Error: the JVM or the platform failed — memory exhausted, stack blown, a class missing at load time. Programs should not catch these (what would you do?), and catching Throwable to "be safe" swallows them.
  • Checked exceptions (Exception and subclasses that are not RuntimeException): conditions a correct program should anticipate — a file may be absent, a network may drop. The compiler forces every caller to catch or declare them.
  • Unchecked exceptions (RuntimeException and subclasses): programming errors and precondition violations — null where an object was required, an index past the end, an argument out of range. No declaration required; they propagate freely.

The next lesson is about the checked/unchecked decision; here, the key is that the class of an exception is the category of failure.

What an exception carries

Throwable t;
t.getMessage()        // the detail message given at construction, or null
t.getCause()          // the exception that caused this one, or null (chaining — lesson 5)
t.getStackTrace()     // StackTraceElement[] — the frames at the point of creation
t.printStackTrace()   // to System.err; loggers do this properly
t.getSuppressed()     // exceptions suppressed during try-with-resources cleanup (lesson 4)
t.toString()          // "java.lang.IllegalArgumentException: the message"

The stack trace is captured when the object is constructed — not when it is thrown. That is why new Exception() is expensive (filling the trace walks the stack) and why creating exceptions for control flow is slow (lesson 6).

Reading a stack trace

Exception in thread "main" java.lang.NumberFormatException: For input string: "4.2"
    at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
    at java.base/java.lang.Integer.parseInt(Integer.java:661)
    at java.base/java.lang.Integer.parseInt(Integer.java:777)
    at com.example.Parser.readAge(Parser.java:42)
    at com.example.Parser.parse(Parser.java:18)
    at com.example.Main.main(Main.java:9)

Read it this way:

  1. The first line: the thread, the exception class, the message. Here the message tells you the bad input exactly.
  2. The frames, top to bottom: innermost first. The top frames are usually library code that detected the problem; scan down to the first frame in your package — Parser.readAge(Parser.java:42) — that is where to look. The frames below show how execution got there.
  3. Caused by: sections (chained exceptions) follow, each with its own trace, and ... 12 more means frames identical to the enclosing trace were omitted.

A stack trace is a gift: it names the exact line. Learn to jump to the first frame of your own code rather than reading from the top.

The common unchecked exceptions, and what they mean

ExceptionWhat it says about your code
NullPointerExceptionA null reference was dereferenced. Since Java 14 the message says which one: Cannot invoke "String.length()" because "name" is null.
ArrayIndexOutOfBoundsExceptionAn index outside 0..length-1; the message gives index and length.
StringIndexOutOfBoundsExceptioncharAt/substring out of range.
IllegalArgumentExceptionA method received an argument it cannot accept — thrown by you in validation.
IllegalStateExceptionThe object was not in a state that allows the call (Iterator.remove twice, a closed stream).
NumberFormatExceptionparseInt/parseDouble on non-numeric text.
ArithmeticExceptionInteger division by zero; BigDecimal non-terminating division.
ClassCastExceptionA downcast to a class the object is not.
UnsupportedOperationExceptionAn optional operation not supported by this implementation (List.of(…).add).
ConcurrentModificationExceptionA collection was modified during iteration.
NoSuchElementExceptionnext() past the end, Optional.get() on empty, Scanner with no token.

Most of these mean a bug in the calling code, not a condition to catch: fix the null, the index, the argument. The exception is the diagnosis.

Throwable versus Exception versus RuntimeException in a catch

catch (Exception e) catches every checked and unchecked exception but not Errors; catch (RuntimeException e) only unchecked; catch (Throwable t) everything including OutOfMemoryError. The last belongs only at the very top of a thread (a framework's request loop) where the intent is to log and keep the process alive — and even there, Errors are usually rethrown.

Exceptions are objects

You can store them, pass them, inspect them, and construct them without throwing. throw needs a Throwable expression: throw new IllegalStateException("closed"). The throw statement ends the method's normal execution immediately; code after it in the block is unreachable.

Interview angle

  • "Difference between Error and Exception?" Errors are JVM-level failures you do not catch; Exceptions are conditions a program may handle.
  • "Checked vs unchecked — which classes?" Unchecked = RuntimeException and its subclasses (and Errors); everything else under Exception is checked.
  • "Is NullPointerException checked?" No — it extends RuntimeException.
  • "When is the stack trace captured?" At construction, in Throwable's constructor.
  • "What does ... 12 more mean?" Frames shared with the enclosing trace were elided.

Key takeaways

  • Throwable → Error (do not catch) and Exception → checked (compiler-enforced) vs RuntimeException (unchecked).
  • Unchecked exceptions usually mean a bug: fix the cause rather than catching.
  • Read a stack trace by finding the first frame in your own code; the message often names the bad value.
  • An exception is an object with a message, a cause and a trace captured at construction.

Common questions

What is the difference between Error and Exception in Java?

An Error signals that the JVM or platform failed — memory exhausted, stack overflowed, a class missing at load time — and programs should not catch it. An Exception is a condition a program might anticipate and recover from, such as a missing file or a bad argument.

Is NullPointerException checked or unchecked?

Unchecked. NullPointerException extends RuntimeException, so no method has to declare or catch it. It signals a bug — a null reference was dereferenced — and since Java 14 its message names which reference was null.

How do you read a Java stack trace?

Start with the first line: the thread, the exception class and the message, which often names the bad value. Then scan the frames, innermost first, down to the first one in your own package — that is the line to look at. Caused by: sections follow for chained exceptions.

What does "... 12 more" mean in a Java stack trace?

It means that many frames identical to the enclosing trace were left out. It appears in Caused by: sections, whose lower frames are usually shared with the exception that wrapped them.

When is an exception's stack trace captured in Java?

When the exception object is constructed, in Throwable's constructor — not when it is thrown. Filling in the trace walks the stack, which is why creating exceptions is relatively expensive and why they should not be used for normal control flow.

Mark as readSign in to keep your place.

Java Exception Hierarchy: Throwable, Error and Stack Traces

Every Java exception extends Throwable, which splits into Error and Exception, checked or unchecked. The common exceptions and how to read a stack trace.

  • Course: Java study plan
  • Module: Exceptions
  • Kind: Lesson
  • Reading time: 13 min
  • Runtime: OpenJDK 18

What is the exception hierarchy in Java?

The Java exception hierarchy is rooted at Throwable, which has two branches. Error covers failures of the JVM itself, such as OutOfMemoryError, which programs should not catch. Exception covers conditions a program may handle: its subclasses are checked, so callers must catch or declare them, except RuntimeException and its subclasses, which are unchecked.

Lesson

When something goes wrong at run time — an index out of range, a file missing, a null dereferenced — Java creates an exception object describing the failure and unwinds the call stack until something catches it. Every exception is an instance of a class in one hierarchy rooted at Throwable, and where a class sits in that hierarchy decides whether the compiler forces you to handle it. This lesson is the map of that hierarchy, the exceptions you will meet daily, and how to read the stack trace you get when one escapes.

The hierarchy

Throwable
├── Error                       — the JVM is in trouble; do not catch
│   ├── OutOfMemoryError
│   ├── StackOverflowError
│   ├── NoClassDefFoundError
│   └── AssertionError
└── Exception                   — something a program might recover from
    ├── IOException             — CHECKED: must be declared or caught
    │   ├── FileNotFoundException
    │   └── UncheckedIOException (RuntimeException, despite the name's neighbourhood)
    ├── SQLException             — checked
    ├── InterruptedException     — checked
    ├── ReflectiveOperationException (ClassNotFoundException, …) — checked
    └── RuntimeException         — UNCHECKED: may be thrown anywhere without declaration
        ├── NullPointerException
        ├── IllegalArgumentException
        │   └── NumberFormatException
        ├── IllegalStateException
        ├── IndexOutOfBoundsException
        │   ├── ArrayIndexOutOfBoundsException
        │   └── StringIndexOutOfBoundsException
        ├── ArithmeticException
        ├── ClassCastException
        ├── UnsupportedOperationException
        ├── ConcurrentModificationException
        ├── NoSuchElementException
        └── DateTimeException

Three tiers to remember:

  • Error: the JVM or the platform failed — memory exhausted, stack blown, a class missing at load time. Programs should not catch these (what would you do?), and catching Throwable to "be safe" swallows them.
  • Checked exceptions (Exception and subclasses that are not RuntimeException): conditions a correct program should anticipate — a file may be absent, a network may drop. The compiler forces every caller to catch or declare them.
  • Unchecked exceptions (RuntimeException and subclasses): programming errors and precondition violations — null where an object was required, an index past the end, an argument out of range. No declaration required; they propagate freely.

The next lesson is about the checked/unchecked decision; here, the key is that the class of an exception is the category of failure.

What an exception carries

Throwable t;
t.getMessage()        // the detail message given at construction, or null
t.getCause()          // the exception that caused this one, or null (chaining — lesson 5)
t.getStackTrace()     // StackTraceElement[] — the frames at the point of creation
t.printStackTrace()   // to System.err; loggers do this properly
t.getSuppressed()     // exceptions suppressed during try-with-resources cleanup (lesson 4)
t.toString()          // "java.lang.IllegalArgumentException: the message"

The stack trace is captured when the object is constructed — not when it is thrown. That is why new Exception() is expensive (filling the trace walks the stack) and why creating exceptions for control flow is slow (lesson 6).

Reading a stack trace

Exception in thread "main" java.lang.NumberFormatException: For input string: "4.2"
    at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
    at java.base/java.lang.Integer.parseInt(Integer.java:661)
    at java.base/java.lang.Integer.parseInt(Integer.java:777)
    at com.example.Parser.readAge(Parser.java:42)
    at com.example.Parser.parse(Parser.java:18)
    at com.example.Main.main(Main.java:9)

Read it this way:

  1. The first line: the thread, the exception class, the message. Here the message tells you the bad input exactly.
  2. The frames, top to bottom: innermost first. The top frames are usually library code that detected the problem; scan down to the first frame in your package — Parser.readAge(Parser.java:42) — that is where to look. The frames below show how execution got there.
  3. Caused by: sections (chained exceptions) follow, each with its own trace, and ... 12 more means frames identical to the enclosing trace were omitted.

A stack trace is a gift: it names the exact line. Learn to jump to the first frame of your own code rather than reading from the top.

The common unchecked exceptions, and what they mean

ExceptionWhat it says about your code
NullPointerExceptionA null reference was dereferenced. Since Java 14 the message says which one: Cannot invoke "String.length()" because "name" is null.
ArrayIndexOutOfBoundsExceptionAn index outside 0..length-1; the message gives index and length.
StringIndexOutOfBoundsExceptioncharAt/substring out of range.
IllegalArgumentExceptionA method received an argument it cannot accept — thrown by you in validation.
IllegalStateExceptionThe object was not in a state that allows the call (Iterator.remove twice, a closed stream).
NumberFormatExceptionparseInt/parseDouble on non-numeric text.
ArithmeticExceptionInteger division by zero; BigDecimal non-terminating division.
ClassCastExceptionA downcast to a class the object is not.
UnsupportedOperationExceptionAn optional operation not supported by this implementation (List.of(…).add).
ConcurrentModificationExceptionA collection was modified during iteration.
NoSuchElementExceptionnext() past the end, Optional.get() on empty, Scanner with no token.

Most of these mean a bug in the calling code, not a condition to catch: fix the null, the index, the argument. The exception is the diagnosis.

Throwable versus Exception versus RuntimeException in a catch

catch (Exception e) catches every checked and unchecked exception but not Errors; catch (RuntimeException e) only unchecked; catch (Throwable t) everything including OutOfMemoryError. The last belongs only at the very top of a thread (a framework's request loop) where the intent is to log and keep the process alive — and even there, Errors are usually rethrown.

Exceptions are objects

You can store them, pass them, inspect them, and construct them without throwing. throw needs a Throwable expression: throw new IllegalStateException("closed"). The throw statement ends the method's normal execution immediately; code after it in the block is unreachable.

Interview angle

  • "Difference between Error and Exception?" Errors are JVM-level failures you do not catch; Exceptions are conditions a program may handle.
  • "Checked vs unchecked — which classes?" Unchecked = RuntimeException and its subclasses (and Errors); everything else under Exception is checked.
  • "Is NullPointerException checked?" No — it extends RuntimeException.
  • "When is the stack trace captured?" At construction, in Throwable's constructor.
  • "What does ... 12 more mean?" Frames shared with the enclosing trace were elided.

Key takeaways

  • Throwable → Error (do not catch) and Exception → checked (compiler-enforced) vs RuntimeException (unchecked).
  • Unchecked exceptions usually mean a bug: fix the cause rather than catching.
  • Read a stack trace by finding the first frame in your own code; the message often names the bad value.
  • An exception is an object with a message, a cause and a trace captured at construction.

Common questions

What is the difference between Error and Exception in Java?

An Error signals that the JVM or platform failed — memory exhausted, stack overflowed, a class missing at load time — and programs should not catch it. An Exception is a condition a program might anticipate and recover from, such as a missing file or a bad argument.

Is NullPointerException checked or unchecked?

Unchecked. NullPointerException extends RuntimeException, so no method has to declare or catch it. It signals a bug — a null reference was dereferenced — and since Java 14 its message names which reference was null.

How do you read a Java stack trace?

Start with the first line: the thread, the exception class and the message, which often names the bad value. Then scan the frames, innermost first, down to the first one in your own package — that is the line to look at. Caused by: sections follow for chained exceptions.

What does "... 12 more" mean in a Java stack trace?

It means that many frames identical to the enclosing trace were left out. It appears in Caused by: sections, whose lower frames are usually shared with the exception that wrapped them.

When is an exception's stack trace captured in Java?

When the exception object is constructed, in Throwable's constructor — not when it is thrown. Filling in the trace walks the stack, which is why creating exceptions is relatively expensive and why they should not be used for normal control flow.

Exercises

Name that exception

Read an integer n and n commands, each of which triggers a runtime exception: parse <text> (Integer.parseInt), index <i> (index into a 3-element array), div <a> <b> (integer division), cast (cast a String held in an Object to Integer), nullcall (call length() on a null String). Catch each exception as RuntimeException and print <simple class name>: <message>; if no exception occurs print ok <result>.

Example: 3 then parse 42, parse x, div 1 0 →

ok 42
NumberFormatException: For input string: "x"
ArithmeticException: / by zero

Catch the specific one first

Read n commands. parse <text> calls Integer.parseInt; divide <a> <b> computes a / b; index <i> reads element i of a three-element array {10, 20, 30}. Run each inside one try with catch blocks ordered most specific first: NumberFormatException → bad number: <text>, ArithmeticException → arithmetic: <message>, ArrayIndexOutOfBoundsException → index: <message>, and a final RuntimeException → other: <simple class name>. On success print the result.

Example: 4 then parse 42, parse x, divide 1 0, index 5 →

42
bad number: x
arithmetic: / by zero
index: Index 5 out of bounds for length 3

In this module: Exceptions

← Checkpoint — Nested classes & lambdas · Checked versus unchecked — the rules and the judgement →