当一个错误不会导致程序崩溃时,这意味着什么

问题描述:

有时候Eclipse会说“你应该调试这条线!!!”但并没有真正关闭程序。然后,我可以继续玩大二,甚至经历了第一次导致错误的相同事件,并获得另一个错误框弹出!当一个错误不会导致程序崩溃时,这意味着什么

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

+0

,如果我们知道什么是错误是这将是有益的。 – 2008-12-15 12:49:23

+1

什么是二大? – 2008-12-15 14:38:55

+0

但是,我的问题是一般?没有具体的错误,我只是好奇为什么一些错误会阻止一个程序,而一些错误不会呢? – Ziggy 2008-12-16 02:23:38

编程错误可以在这些类别进行分类:

  1. 编译时错误,这是由在编译时编译器捕获并没有纠正他们,这是不可能在所有运行的程序。
  2. 运行时错误,它不会被编译器捕获,但会使计算机处于无法找出自己要做什么的情况,例如未处理的异常。大多数情况下,这会导致程序在运行时崩溃并崩溃。
  3. 逻辑错误,这是计算机完全可以接受的,因为它是一个有效的计算机程序,但不会产生您期望的结果。由于电脑不知道你的意图,电脑无法捕捉到他们。

实际上,尽可能让错误尽可能致命是件好事。它使我们更快地找到它们并更轻松地纠正它们。这就是为什么在“安全”的语言(如Java)中,我们检查了异常,而未处理的异常将导致应用程序立即崩溃,而不是继续运行,并可能产生不正确的结果。

+0

我不同意将错误尽可能致命是件好事。完全有可能产生对程序不致命的错误,并且可以(也应该)从错误中恢复。在所有错误条件下做*事*是很重要的,但它不应该总是终端。 – Adrian 2008-12-15 15:50:41

我想你的情况,这是关于异常发生在什么线程(你的应用程序是一个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)行时看到行为上的差异。

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

在您的储蓄账户,他们所做的follwoing行:

Account -= Interest; 

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

前面的回答中得到这一权利Java的一部分:

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

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

在许多更简单的Java应用程序中,只有1个非守护程序线程(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” S和“B” S,直到5日“ B”,此时你会得到我们抛出异常的堆栈跟踪,而‘A’的继续(在‘B’S不继续,因为线程刚刚去世,因为未处理的异常。)

现在,如果你回去换t1.setDaemon(false)t1.setDaemon(true),并再次运行,你会看到,当T2终止,因为异常的,有没有非守护线程剩下的,JVM将退出。

,回答了“为什么一些错误不关闭JVM”的问题。但是它并没有回答关于Eclipse为什么会弹出一个调试器的部分问题。

这个问题的答案是简单的(但我对此有点不太确定的...别人附和):Eclipse调试器暂停任何时候一个线程终止,因为未处理的异常。它假定你并不是说线程死掉了,而且你需要修复这个bug。我相信它实际上是在观察java.lang.ThreadDeath异常,并在任何时候抛出异常。