What is a StackOverflowError in Java, and what most commonly causes it?
answer
- Per-thread stack, one frame per call
- Missing/unreachable base case in recursion
- Error not Exception — fix, don't catch
- -Xss tunes stack size (workaround)
- Trace shows the same method repeating
basics
~20 sIt is an error thrown when a thread runs out of stack space. The usual cause is recursion that never stops because it is missing a base case, so methods keep calling themselves until the stack fills up.
solid answer
~40 sjava.lang.StackOverflowError is thrown when a thread exhausts its call stack. Each method call pushes a stack frame (parameters, local variables, return address); when the total frame depth exceeds the per-thread stack size, the JVM throws this error. By far the most common cause is unbounded or infinitely deep recursion — a recursive method with a missing or unreachable base case, or mutual recursion between two methods. Less often it comes from genuinely very deep but finite recursion, or methods with unusually large stack frames (many or large local variables). It is an Error, not an Exception, signalling an abnormal condition you normally fix by correcting the recursion rather than catching it. Contrast it with OutOfMemoryError, which is about the heap or metaspace, not the thread stack.
go deeper
Knows it comes from infinite/too-deep recursion with a missing base case, and that the stack trace shows the same method repeating.
Explains stack frames per call, the per-thread fixed stack, distinguishes it from OutOfMemoryError, and knows -Xss exists.
Discusses fixing via iteration vs base case, mutual/accidental recursion, large-frame cases, and the trade-offs of raising -Xss in multithreaded apps.
Reasons about stack sizing across many threads, sets diagnostics/guardrails, and weighs algorithmic redesign (iteration, explicit stacks) over flag tuning at the system level.
## What the stack is When a Java program runs, every **thread** has its own region of memory called the **call stack** (or just "the stack"). Each time a method is called, the JVM pushes a **stack frame** onto that thread's stack. A stack frame holds the method's **parameters**, its **local variables**, the **operand stack** the bytecode uses for computation, and bookkeeping like the **return address** (where to continue when the method finishes). When the method returns, its frame is **popped** off. So the stack grows as calls nest deeper and shrinks as they return. The stack is a **fixed-size** region per thread. It is not the same memory as the **heap** (where objects created with `new` live). The stack is small and bounded; the heap is large. ## What the error is `java.lang.StackOverflowError` is thrown when a thread tries to push another stack frame but there is **no room left** — the stack has been exhausted. In Java this is a subclass of `Error` (specifically `VirtualMachineError`), not of `Exception`. The convention is that `Error`s represent serious conditions you should **not** normally try to recover from; you fix the root cause instead. ## The dominant cause: runaway recursion **Recursion** is when a method calls itself (directly or indirectly). Correct recursion always has a **base case** — a condition that stops the calls and lets them unwind. If the base case is missing, never reached, or the recursion otherwise never terminates, each call pushes a new frame and none are popped, so the stack fills and overflows. ```java int count(int n) { return 1 + count(n + 1); // never stops: no base case, n only grows } ``` This includes **mutual recursion** (method A calls B, B calls A, with no terminating condition) and accidental infinite recursion such as a getter that returns itself, or `toString()` that prints an object that calls `toString()` again. ## Other, rarer causes - **Genuinely deep but finite recursion** — e.g. recursing over a very long linked list or a degenerate (unbalanced) tree thousands deep. Here the logic is correct but the depth simply exceeds the stack size. - **Large stack frames** — a method with very many or very large local variables uses more stack per call, so fewer calls fit before overflow. ## Stack size and the -Xss flag The per-thread stack size is configurable with the JVM flag **`-Xss`** (for example `-Xss1m` for a 1-megabyte stack). A larger stack allows deeper recursion before overflow; a smaller stack overflows sooner. Tuning `-Xss` can buy headroom for legitimately deep recursion, but it is a **workaround, not a fix** for a missing base case — infinite recursion overflows any finite stack. Note that increasing every thread's stack also increases total memory use, which matters in highly multithreaded programs. ## How to diagnose and fix The stack trace of a `StackOverflowError` typically shows the **same method (or small cycle of methods) repeating** many times — that repetition is the fingerprint of the runaway recursion. The fix is almost always to **add or correct the base case**, or to **convert the recursion to iteration** (a loop with an explicit stack/queue) so depth is bounded by heap rather than stack. ## Contrast with OutOfMemoryError `StackOverflowError` is about a **single thread's stack** being exhausted. `OutOfMemoryError` is about the **heap** (too many/too-large live objects) or **metaspace** (class metadata) being exhausted. They are different memory regions and different root causes; do not confuse the two.
- How would you fix code that legitimately needs very deep recursion?Convert it to iteration with an explicit data structure (a loop plus a heap-allocated stack/queue), or restructure to tail-recursion-friendly iteration, so depth is bounded by heap memory instead of the fixed thread stack. Bumping -Xss only buys a little headroom.
- Why is StackOverflowError an Error and not an Exception?Errors signal abnormal JVM conditions you normally shouldn't recover from. The right response is to fix the cause (the recursion), not to catch and continue, since after an overflow the thread's state is suspect.
saying these in an interview costs you the question
- Saying StackOverflowError is about the heap — it is the thread stack
- Confusing it with OutOfMemoryError
- Claiming you should routinely catch it instead of fixing the recursion
- Thinking -Xss can cure truly infinite recursion (it cannot)