A previous answer gets the java-part of this right:
If an exception occurs in your main
thread, it may be terminal, but if it
occurs in another thread it is not
terminal. It's terminal for the main
thread if the other threads in the
application are daemon threads.
The bigger truth is that the JVM that your application is running in will shut down when there are no non-daemon threads still running. That, or an explicit call to System.exit (or an outright JVM crash) are the only ways the JVM will completely exit.
In many simpler Java applications, there is only 1 non-daemon thread (the thread the JVM started to run your main() in at start up.) Because, in the simple case, the thread running our code is the only non-daemon thread, we get the impression that an unhandled exception causes the JVM to exit. That is not true, unless that thread happens to be the only remaining non-daemon thread.
You can prove this to yourself with the following little program:
public class TestMain {
public static void main(String[] args) {
Thread t1 = new Thread() {
public void run() {
while(true) {
System.out.println("A");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("t1 interrupted.");
}
}
}
};
t1.setDaemon(false);
Thread t2 = new Thread() {
public void run() {
int count = 0;
while(true) {
if(count < 5) {
System.out.println("B");
count++;
} else {
throw new RuntimeException("Intentional RuntimeException!");
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("t2 interrupted.");
}
}
}
};
t2.setDaemon(false);
t1.start();
t2.start();
}
}
If you run this, you'll notice that you get intermixed "A"s and "B"s, until the 5th "B", at which point you get a stack trace of the exception we threw, and the "A"'s continue (the "B"s do not continue, because that thread just died because of the unhandled exception.)
Now, if you go back and change t1.setDaemon(false)
to t1.setDaemon(true)
, and run again, you'll see that when t2 terminates because of the exception, there are no non-daemon threads remaining, and the JVM will exit.
That answers the "why do some bugs not close the JVM" question. But it doesn't answer the part of the question about why Eclipse pops up a debugger.
The answer to that is simpler (but I'm a bit less certain about it...someone else chime in): the Eclipse debugger suspends any time a thread dies because of an unhandled exception. It's making the assumption that you didn't mean for the thread to die, and that you need to fix the bug. I believe it's actually watching for the java.lang.ThreadDeath exception, and suspending anytime it gets thrown.