'Will exception in one thread cause application to stop?
I have six threads running in my application. If one thread throws a StackOverFlow exception, will all threads or application stop working?
Solution 1:[1]
Usually - no,
exception in one thread does not kill another thread;
unless....
A little longer story
There are two types of threads in Java: Normal Threads and Daemon Threads, and they differ only in what happens when they exit.
When a thread exits, the JVM performs an inventory of running threads, and
if only daemon threads are left alive
JVM initiates an orderly shutdown (meaning, it shuts down after main thread finishes execution).
When the JVM halts, any remaining daemon threads are abandoned — finally blocks are not executed, stacks are not unwound — the JVM just exits.
So, when you have an unhandled exception in your thread, one of two possible scenarios may occur:
- JVM will shutdown - your thread was the last normal thread, and after JVM performs yet another inventory check following this thread's exit, it will shut down, as there are no other normal threads left (conceptually JVM considers, that nothin important is left running, as daemon threads should never be used for important/unsafe operations);
- JVM will continue running - your thread was not the last normal thread and after an unhandled exception happened in it, JVM will continue running.
For example, in this case:
public class EntryPoint {
public static void main(String[] args) throws Exception {
Thread t = new Thread(() -> {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(1000);
System.out.println("Thread " + Thread.currentThread().getName() + " " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.setDaemon(true);
t.start();
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
if (i == 4) {
throw new StackOverflowError("JVM exits in this case.");
}
System.out.println("Call number " + i);
}
}
}
your application will crash as soon as an exception is thrown, as there are no normal threads left running;
whereas, in this case:
public class EntryPoint {
public static void main(String[] args) throws Exception {
Thread t = new Thread(() -> {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(1000);
System.out.println("Thread " + Thread.currentThread().getName() + " " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.setDaemon(false);
t.start();
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
if (i == 4) {
throw new StackOverflowError("JVM won't exit in this case.");
}
System.out.println("Call number " + i);
}
}
}
a normal thread, referred by t, will continue its execution.
Final notes
Note, that when the JVM starts up (Java program starts), all the threads it creates (such as garbage collector and other housekeeping threads) are daemon threads, except the main thread, which is a normal thread; however, if you create a new thread, it inherits the type from the thread it was created in;
The only reason I explicitly set the
.setDaemon(true), in the first code snippet, is that the thread type is inherited from the thread that created it.
Solution 2:[2]
No.
If StackOverflowError occurs, the thread that ran the code that is responsible for it goes through the normal procedure: It will throw that throwable from that method (throwing a throwable is just like return; in the sense that it exits the method just like return would, with a result: That throwable. But it's not returned, it's thrown - to see it, you'd use a catch block). The method that invoked the method that threw the SOError now throws it. This means every method, in sequence, keeps returning, until one of two things happens:
Somewhere in this chain, the method that invoked the method that invoked the method that threw the SO was doing so in a
try{}block where an associatedcatchblock is catchingStackoverflowErroror some parent type of that (ErrororThrowable). In that case, code continues in that catch block and the thread just keeps running at that point.The exception bubbles all the way to the top, to the
run()method where the thread started, and exits the run method in that way (by throwing it onwards). In this case, the JVM itself catches it. Threads will catch any and all throwables that the run() method they started the thread with end up throwing. In which case, the thread is of course shut down (the run() method returned - that's what threads do when the run method returns), and the throwable is handed to the thread's uncaught exception handler. You can set that handler if you want. By default, it dumps a bunch of useful info toSystem.errand that's all the deafult handler does.
Other threads are not affected in the slighest.
But I read somewhere memory errors lead to unstable VMs!
StackOverflowError smacks of OutOfMemoryError, but to be clear, they are not the same. A major caveat is often stated for OOMError, but does not apply to stack overflow: If an OOME occurs anywhere in the VM you should assume that code will end up buggy - most java code is not tested to properly handle this situation, and in practice the VM probably isn't quite guaranteeing stable behaviour in the face of a full heap either. So if an OOME happens to you, the VM is best considered unstable (exit it and restart at some point, sooner better than later), and weird things may happen.
But that's OOME. It does not apply to stack overflow, because each thread has its own, entirely independent stack.
... hmm, my VM still shut down
Well, if you don't catch that SOErr the thread will end up exiting because the run() method returns, and the VM will shut down automatically if all there are no running threads* left. This isn't a particularly good strategy to shut down VMs (just call System.exit if you want the VM to shut down); it's more of a ¯\(?)/¯ I guess there's nothing left to do, might as well just shut down then situation.
Thus, if you have only one thread, it runs code that ends up throwing SOError, you don't catch it (and usually you shouldn't), then yeah, the VM will shut down, but by design: That thread will now exit, the VM realizes no active threads are left, and will then shut down.
*) Technically, threads with the daemon flag set do not 'count'; if all non-done threads are daemon threads, the VM shuts down. Given that VM shutdows are best done with System.exit, this factoid is essentially irrelevant.
Solution 3:[3]
No if it's not a main thread. Every thread in JVM has its own Stack in the memory. You can control its size by -Xss parameter.
By the way, you can easily find an answer by writing a simple application with 2 running threads. One can fail with StackOverflowError when doing infinite recursion, then you will see how the 2nd thread behaves. Give it a try.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | rzwitserloot |
| Solution 3 |
