Under what circumstances does a finally block NOT execute?
answer
- System.exit() in try -> finally skipped
- Runtime.halt skips even shutdown hooks
- JVM crash / kill -9 / OOM process death
- Thread killed or infinite loop -> never reached
- Thrown exceptions do NOT skip finally
basics
~20 sfinally is skipped if the JVM stops before reaching it, mainly when you call System.exit() in the try, or if the JVM crashes or the thread is killed. An infinite loop in try also means it never gets there.
solid answer
~40 sfinally's guarantee assumes the thread keeps running and eventually leaves the try region. It is broken when the program never gets that far. The classic case is System.exit(int) (or Runtime.halt) inside the try or catch: that terminates the JVM immediately and pending finally blocks do not run. Other cases: a fatal JVM crash (native error, OutOfMemoryError that kills the process, kill -9, power failure), the executing thread being terminated abruptly, or control simply never reaching finally because of an infinite loop or an indefinitely blocked call inside try. Note that a thrown Error or RuntimeException does NOT skip finally; it propagates after finally runs. The mental model: finally protects against exceptions and early jumps, not against the whole JVM going away.
go deeper
Knows the headline exception: System.exit in try means finally is skipped.
Lists the full set (System.exit/halt, JVM crash, thread death, never-reached) and knows thrown exceptions do not skip finally.
Distinguishes recoverable-Error propagation (finally runs) from process death (skipped) and reasons about durability safeguards beyond finally.
Designs for partial-failure and process-death scenarios, choosing shutdown hooks, WAL, or transactional boundaries where finally's guarantee is insufficient.
## The guarantee and its boundary The finally block is often summarized as "always runs", but the precise statement is: finally runs whenever control leaves the associated try (and catch) region **and the JVM/thread is still alive to execute it**. The exceptions to the rule are all situations where that second condition fails. ## Cases where finally does NOT run ### 1. System.exit() The most-tested case. `System.exit(int)` requests immediate JVM shutdown. It runs registered shutdown hooks but does **not** unwind the stack, so any pending finally blocks are abandoned: ```java try { System.exit(0); } finally { System.out.println("never prints"); // skipped } ``` `Runtime.getRuntime().halt(int)` is even more abrupt: it skips shutdown hooks too. ### 2. JVM termination / crash If the JVM dies rather than returns, finally cannot run: - A fatal native error or hard crash (segfault in native code, `kill -9`, machine power loss). - An `OutOfMemoryError` or other `Error` that the runtime cannot recover from and that brings the process down. (A *recoverable* Error still triggers finally as it propagates; it is process death that skips it.) ### 3. The thread is terminated abruptly If the thread executing the try is stopped at a low level (the deprecated `Thread.stop`, or the VM forcibly tearing down a thread during shutdown), its finally blocks may not run. ### 4. Control never reaches finally A subtle category: finally only runs if the try body is *exited*. If the try contains an infinite loop, or blocks forever on I/O or a lock, execution never leaves try, so finally is simply never reached. This isn't really an exception to the rule; control just never got there. ## What does NOT skip finally (common confusion) - A thrown `RuntimeException`, checked exception, or recoverable `Error`: finally runs, then the throwable continues propagating. - `return`, `break`, `continue` in try or catch: finally runs before the jump completes. - An exception thrown inside a `catch` block: the already-attached finally still runs. ## Practical takeaway Because System.exit and crashes can skip finally, do not rely on finally for *external* invariants that must survive process death (e.g. flushing a critical audit record) without additional safeguards like shutdown hooks, transactions, or write-ahead logs.
- Does System.exit run shutdown hooks, and does Runtime.halt?System.exit runs registered shutdown hooks before terminating; Runtime.halt skips even those, terminating immediately.
- If a catch block throws a new exception, does finally still run?Yes. The finally attached to the same try executes before the new exception propagates.
saying these in an interview costs you the question
- Claiming a normal thrown exception skips finally (it does not)
- Forgetting System.exit is the headline 'finally does not run' case
- Assuming shutdown hooks substitute for finally semantics
- Thinking finally guarantees external durability across a crash