Errors you should not catch in Java
OutOfMemoryError, StackOverflowError and why.
When the JVM itself is in trouble
Errors signal problems a program usually can't recover from. OutOfMemoryError: the heap is exhausted. StackOverflowError: the thread's stack is full, usually from runaway recursion. Both extend VirtualMachineError → Error — not Exception, so catch (Exception e) won't catch them.
A recursion with no exit
What happens?
int down(int n) {
return down(n - 1);
}
void main() {
System.out.println(down(10));
}Prints 0Throws StackOverflowErrorRuns foreverThrows OutOfMemoryError
Show the answer
Every call adds a stack frame, and nothing stops the recursion. The thread's stack fills up and the JVM throws StackOverflowError — fast, not forever.
Every recursion needs a base case
The fix isn't a catch — it's the code. A recursive method must have a base case that stops it. Without the first line, factorial(5) would crash with StackOverflowError.
int factorial(int n) {
if (n <= 1) return 1; // base case
return n * factorial(n - 1);
}Catching Errors to carry on
Errors can be caught, but the code that was interrupted may have left objects half-updated, and after an OutOfMemoryError there may be no memory even to handle it. Carrying on risks wrong results. Fix the cause; catch Throwable only at the very top — to log and shut down cleanly.
try {
handle(request);
} catch (OutOfMemoryError e) { // bad idea
// retry? continue? state is unknown
}Days of uptime, then OOM
A server throws OutOfMemoryError after several days of running. What's the better approach than catching it?
Think about it, then reveal the answer
Growth over days points to a memory leak — e.g. an ever-growing cache or static map. Take a heap dump to find what's piling up and fix it, or raise the heap limit with **-Xmx** if the usage is legitimate.
Production settings
Ops teams start Java services with -XX:+HeapDumpOnOutOfMemoryError, so a crash leaves a heap dump to analyze. -Xmx sets the maximum heap and -Xss sets the thread stack size — tuning knobs, not substitutes for fixing leaks and broken recursion.
Key takeaways
- StackOverflowError: usually recursion without a working base case
- OutOfMemoryError: heap exhausted — a leak, or -Xmx too small
- Errors are unchecked; catch (Exception e) won't catch them
- Fix the cause; catch Throwable only at the very top, to log
The Q&A site Stack Overflow, launched in 2008, took its name from exactly this kind of error — the stack overflow every programmer meets sooner or later.
Practice questions
What does this print?
int depth(int n) {
return depth(n + 1);
}
void main() {
System.out.println(depth(0));
}- Throws StackOverflowError
- Throws OutOfMemoryError
- Prints 0
- Runs forever
Check your answer
Throws StackOverflowError. Every call adds a stack frame and nothing stops the recursion, so the thread's stack fills up.
A server throws OutOfMemoryError after several days of uptime. A teammate suggests catching OutOfMemoryError around each request and carrying on. Better approach?
- Find the leak (e.g. an ever-growing cache) from a heap dump, or raise -Xmx if usage is legitimate
- Catch Throwable instead to be extra safe
- Call System.gc() inside the catch block
- Catch it and retry the request in a loop
Check your answer
Find the leak (e.g. an ever-growing cache) from a heap dump, or raise -Xmx if usage is legitimate. Growth over days points to a leak. Catching the error just postpones the crash and may leave data half-updated.