当一个bug没有导致程序崩溃时,它意味着什么

时间:2008-12-15 12:45:28

标签: java eclipse crash

有时候Eclipse出现了“嘿,你应该调试这条线!!!”但实际上并没有关闭该计划。然后我可以继续玩大二,甚至第一次经历导致错误的相同事件并弹出另一个错误框!

错误很简单,我会修复它,我只是想知道为什么有些bug是终端而有些不是?有什么区别?

4 个答案:

答案 0 :(得分:7)

编程错误可以归类为以下类别:

  1. 编译时错误,编译时在编译时捕获并且没有更正它们,根本无法运行程序。
  2. 运行时错误,它不会被编译器捕获,而是使计算机处于无法自行解决的情况,例如未处理的异常。大多数情况下,这会导致程序在运行时失败并崩溃。
  3. 逻辑错误,计算机完全可以接受,因为它是一个有效的计算机程序,但不会产生您期望的结果。由于计算机不知道你的意图,计算机无法捕获它们。
  4. 在实践中,尽可能使错误尽可能致命,这是一件好事。它使我们能够更快地找到它们并更容易地纠正它们。这就是为什么在诸如Java之类的“更安全”的语言中,我们检查了异常,未处理的异常将导致应用程序立即崩溃而不是继续发生并可能产生不正确的结果。

答案 1 :(得分:2)

我想在你的情况下,它是关于异常发生在哪个线程(你的应用程序是一个GUI应用程序,对吧?)。如果主线程中发生异常,则它可能是终端,但如果它出现在另一个线程中,则它不是终端。如果应用程序中的其他线程是守护程序线程,则它是主线程的终端。当线程是守护进程时,应用程序将在它们完成之前终止,无论它们的状态如何。如果它们不是守护进程,则应用程序将在终止之前等待它们完成。

我不太了解Eclipse框架,但我想它能够处理GUI线程中的异常。

我已经包含了一个示例我的示例的Java应用程序;

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");
    }
}

取消标记t.setDaemon(true)行时,您会看到行为上的差异。

答案 2 :(得分:2)

之前的回答得到了正确的java部分:

  

如果您的主要发生异常   线程,它可能是终端,但如果它   它发生在另一个线程中   终奌站。这是主要的终端   线程如果其他线程在   应用程序是守护程序线程。

更大的事实是,当没有非守护程序线程仍在运行时,运行应用程序的JVM将关闭。那个,或者对System.exit的显式调用(或彻底的JVM崩溃)是JVM完全退出的唯一方式。

在许多更简单的Java应用程序中,只有一个非守护程序线程(JVM在启动时开始运行你的main()的线程。)因为,在简单的情况下,运行我们的代码的线程是唯一的非守护程序线程,我们得到一个未处理的异常导致JVM退出的印象。事实并非如此,除非该线程碰巧是唯一剩下的非守护程序线程。

您可以通过以下小程序向自己证明:

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();
    }
}

如果你运行它,你会注意到混合了“A”和“B”,直到第5个“B”,此时你得到了我们抛出的异常的堆栈跟踪,并且“一个“继续”(“B”不继续,因为该线程因未处理的异常而死亡。)

现在,如果您返回并将t1.setDaemon(false)更改为t1.setDaemon(true),然后再次运行,您会看到当t2因异常而终止时,没有剩余的非守护程序线程,并且JVM将退出。

回答“为什么有些bug不能关闭JVM”的问题。但它没有回答有关Eclipse弹出调试器的问题的部分内容。

对此的答案更简单(但我对它有点不太确定......其他人也会加入):Eclipse调试器会因为未处理的异常而导致线程死亡。它假设您并不意味着线程死亡,并且您需要修复错误。我相信它实际上是在监视java.lang.ThreadDeath异常,并且只要它被抛出就会挂起。

答案 3 :(得分:0)

例如,想象一下您的银行使用的一个软件。

在您的储蓄账户中,他们已经做了以下几行:

Account -= Interest;

这显然是一个错误,但它不会使系统崩溃。