views:

544

answers:

4

The title says it all. No dire need to know, I'm just curious. Sometimes Eclipse comes up saying "hey you should debug this line!!!" but doesn't actually close the program. I can then continue to play big two, and even go through the same events that caused the error the first time and get another error box to pop up!

The bug is simple, I'll fix it, I just want to know why some bugs are terminal and some are not? What's the difference?

+5  A: 

Programming mistakes can be categorized in these categories:

  1. Compile-time errors, which are caught by the compiler at the time of compilation and without correcting them, it's not possible to run the program at all.
  2. Run-time errors, which are not caught by the compiler but put the computer in a situation which it cannot figure out what to do by itself, such as unhandled exceptions. Most of the times, this will cause the program to fail at run time and crash.
  3. Logical errors, which are perfectly acceptable by the computer, as it is a valid computer program, but does not produce the result you expect. There is no way a computer can catch them since computer doesn't know your intention.

In practice, it's a good thing to make errors be as deathly as possible as soon as they occur. It makes us find them sooner and correct them easier. This is why in languages such as Java, we have checked exceptions and unhandled exceptions will cause the application to crash immediately instead of going on and producing probably incorrect results.

Mehrdad Afshari
I disagree with the idea that it's a good thing to make errors as deadly as possible. It's perfectly possible to have an error that isn't fatal to the program and can (and should) be recovered from. It's important to do *something* with all error conditions, but it shouldn't always be terminal.
Adrian
It's important to know exceptions are not the same as errors. If you can handle something in your code, it shouldn't be considered a programming *mistake* which is what I'm talking about. Yeah, it might not be dropping to shell, but it's usually like that. And I meant it in development phase.
Mehrdad Afshari
Even programming errors shouldn't be terminal if they're survivable. If they're limited to a small and rarely used part of the overall functionality and don't impact on the rest of the program flow, then you want them to be survived if possible once the program reaches the real world.
Adrian
+2  A: 

I would guess that in your case, it's all about what thread the Exception occurred in (your app is a GUI app, 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. When the threads are daemon, the application will terminate before they have completed, regardless of their status. If they are not daemon, the application will wait for them to complete before terminating.

I don't know the Eclipse framework that well, but I imagine it is able to cope with an exception in the GUI thread.

I've included a sample java app that illustrates my example;

public class ThreadTest {

    public static void main(String[] args) {

        Runnable test = new Runnable() {

            public void run() {
                try {
                    System.out.println("Sleeping");
                    Thread.sleep(5000);
                    System.out.println("Slept");
                } catch (InterruptedException e) {
                }
            }
        };

        Thread t = new Thread(test);
        //t.setDaemon(true);
        t.start();

        System.out.println("Waiting to fail");
        throw new RuntimeException("Error");
    }
}

You will see the difference in behavior when untagging the t.setDaemon(true) line.

Bent André Solheim
Thank you thank you! Curiosity sated.
Ziggy
A: 

For example, imagine a piece of software used by your bank.

In you savings account they have made the follwoing line:

Account -= Interest;

Which obviously is a bug, but it does not crash the system.

Gamecat
I think that in this case, it's not exactly "bug" in its broadest sense that is meant, but application exception; an exception that is not handled by any application code.
Bent André Solheim
While Gamecat is correct, I think the OriginalPoster was asking about exceptions that generate stacktrace and kill a thread, but leave the main application alive, in a bad state.
Karl
+2  A: 

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.

Jared
Thank you muchly! That hit the spot too!
Ziggy