Common Errors in Java

Naveen AnamaneniUpdated · 5 min read

Exceptions describe problems in your program's logic. Errors describe something more serious: the JVM itself has run out of a resource it needs. The two you'll meet are StackOverflowError, when method calls nest too deeply, and OutOfMemoryError, when the heap is full. Both extend Error, not Exception, which is Java's way of saying "you usually can't recover from this; fix the cause".

Running Out of Stack and Heap

Too many nested calls fill the stack; too many live objects fill the heap
Errors.java▶ Try it
import java.util.ArrayList;
import java.util.List;
 
public class Errors {
    static int depth = 0;
 
    static void dive() {
        depth++;
        dive();
    }
 
    public static void main(String[] args) {
        try {
            dive();
        } catch (StackOverflowError e) {
            System.out.println("StackOverflowError after " + depth + " calls");
        }
 
        List<long[]> hog = new ArrayList<>();
        try {
            while (true) {
                hog.add(new long[1_000_000]);
            }
        } catch (OutOfMemoryError e) {
            int arrays = hog.size();
            hog.clear();
            System.out.println("OutOfMemoryError: " + e.getMessage()
                + " after " + arrays + " arrays of 8 MB");
        }
    }
}
Output
StackOverflowError after 10473 calls
OutOfMemoryError: Java heap space after 507 arrays of 8 MB

How it works

  1. Stack: each method call gets a frame on its thread's stack (its parameters and local variables). dive() calls itself forever with no stopping condition, so frames pile up until the stack is full, and Java throws StackOverflowError. The exact count depends on the stack size and the JVM.
  2. Heap: every new long[1_000_000] takes 8 MB on the heap. The list keeps a reference to each one, so the garbage collector can't free any of them. When the heap is full, Java throws OutOfMemoryError: Java heap space. The count depends on the heap size (try running with -Xmx64m to make it smaller).
  3. These examples catch the errors only to show them. hog.clear() releases the memory so the program can finish.

Causes and Fixes

ErrorUsual causeFix
StackOverflowErrorRecursion with a missing or wrong base caseAdd or correct the base case
StackOverflowErrorVery deep but correct recursionRewrite as a loop (see "Recursion vs Iteration"), or increase the stack with -Xss
StackOverflowErrorTwo methods calling each other, such as toString() methods that print each otherBreak the cycle
OutOfMemoryError: Java heap spaceCollections that grow forever (caches, lists of logs)Remove old entries; bound the size
OutOfMemoryError: Java heap spaceLoading a huge file into memory at onceProcess it in pieces
OutOfMemoryError: Java heap spaceThe program genuinely needs more memoryRaise the limit with -Xmx, for example -Xmx2g

Why You Shouldn't Catch Errors

When an Error happens, the JVM may be in a broken state: an OutOfMemoryError can strike in the middle of any allocation, even inside library code, leaving objects half-updated. Catching it and carrying on usually leads to stranger failures later. The right response is to let the program stop, read the error, and fix the cause. Production servers are often started with -XX:+HeapDumpOnOutOfMemoryError, which saves a snapshot of the heap for analysis when memory runs out.

Common Mistakes

Recursion without a base case, or with one that's never reached. Trace a small input by hand first.

Treating OutOfMemoryError as "buy more RAM". Usually something is holding references it shouldn't.

Catching Error or Throwable to keep a program alive. It hides a broken state.

Interview Corner

What causes StackOverflowError and OutOfMemoryError?

StackOverflowError is thrown when a thread's call stack runs out of space, almost always because of infinite or excessively deep recursion. OutOfMemoryError is thrown when the JVM can't allocate an object because the heap (or another memory area) is exhausted and garbage collection can't free enough, usually because objects are still referenced, as in an ever-growing collection. Both extend Error and indicate conditions applications normally shouldn't try to catch.

Can you catch an OutOfMemoryError?

Technically yes, since it's a Throwable, but you usually shouldn't. The JVM may be in an inconsistent state, and continuing can cause unpredictable failures. It's better to fix the cause, raise the heap size if justified, or let the process restart, collecting a heap dump to investigate.

Practice

  1. Easy: Write a recursive factorial(int n) with a correct base case. Then remove the base case and observe the error.
  2. Harder: Run Errors.java with java -Xmx64m Errors.java and then with -Xmx256m. How does the number of arrays change, and why?

Quick check: Common errors

4 questions
1What usually causes StackOverflowError?
2Why can't the garbage collector free objects in an ever-growing list?
3Do Errors extend Exception?
4Which JVM option raises the maximum heap size?

Key Takeaways

Was this tutorial helpful?

Lesson 218 of 482