что это значит, когда ошибка не приводит к сбою программы - PullRequest
0 голосов
/ 15 декабря 2008

Иногда появляется Eclipse, говоря: «Эй, ты должен отладить эту строку !!!» но на самом деле не закрывает программу. Затем я могу продолжить играть два больших и даже пройти через те же события, которые вызвали ошибку в первый раз, и получить еще одно окно ошибки!

Ошибка проста, я исправлю ее, я просто хочу знать, почему некоторые ошибки являются терминальными, а некоторые нет? Какая разница?

Ответы [ 4 ]

7 голосов
/ 15 декабря 2008

Ошибки программирования можно разделить на следующие категории:

  1. Ошибки времени компиляции, которые обнаруживаются компилятором во время компиляции, и без их исправления программа вообще не может быть запущена.
  2. Ошибки времени выполнения, которые не улавливаются компилятором, но ставят компьютер в ситуацию, в которой он не может понять, что делать самому, например необработанные исключения. В большинстве случаев это приводит к сбою программы во время выполнения и сбою.
  3. Логические ошибки, которые вполне допустимы для компьютера, поскольку это действительная компьютерная программа, но не дают ожидаемого результата. Компьютер не может их поймать, так как компьютер не знает вашего намерения.

На практике хорошо, чтобы ошибки были как можно более опасными, как только они появляются. Это заставляет нас быстрее их находить и исправлять. Вот почему в «более безопасных» языках, таких как Java, мы проверили исключения, а необработанные исключения приведут к немедленному падению приложения, а не к продолжению и, возможно, к получению неверных результатов.

2 голосов
/ 15 декабря 2008

Предыдущий ответ получает 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» и «B» до 5-го «B», после чего вы получаете стековую трассировку исключения, которое мы сгенерировали, и « A "продолжается (" B "не продолжается, потому что этот поток только что умер из-за необработанного исключения.)

Теперь, если вы вернетесь назад и измените t1.setDaemon(false) на t1.setDaemon(true) и снова запустите, вы увидите, что когда t2 завершает работу из-за исключительной ситуации, не останется потоков, не являющихся демонами, и JVM завершит работу. .

Это отвечает на вопрос «почему некоторые ошибки не закрывают JVM». Но это не отвечает на часть вопроса о том, почему в Eclipse появляется отладчик.

Ответ на этот вопрос более прост (но я немного менее уверен в этом ... кто-то еще вмешивается): отладчик Eclipse приостанавливает каждый раз, когда поток умирает из-за необработанного исключения. Это делает предположение, что вы не хотели, чтобы поток умер, и что вам нужно исправить ошибку. Я полагаю, что на самом деле он отслеживает исключение java.lang.ThreadDeath и приостанавливает его в любое время.

2 голосов
/ 15 декабря 2008

Я полагаю, что в вашем случае все зависит от того, в каком потоке произошло Исключение (ваше приложение является приложением с графическим интерфейсом, верно?) Если в вашем основном потоке возникает исключение, оно может быть терминальным, но если это происходит в другом потоке, это не терминал. Это терминал для основного потока, если другие потоки в приложении являются потоками демона. Когда потоки являются демонами, приложение завершает работу до того, как они завершатся, независимо от их статуса. Если они не являются демонами, приложение будет ожидать их завершения до завершения.

Я не очень хорошо знаю инфраструктуру 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).

0 голосов
/ 15 декабря 2008

Например, представьте себе часть программного обеспечения, используемого вашим банком.

На вашем сберегательном счете сделана следующая строка:

Account -= Interest;

Что, очевидно, является ошибкой, но не приводит к краху системы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...