Подтвердить что ты не робот

Каковы обстоятельства, при которых блок finally {} не будет выполняться?

В блоке Java try{} ... catch{} ... finally{} код в finally{} обычно считается "гарантированным" для запуска независимо от того, что происходит в try/catch. Однако я знаю, по крайней мере, о двух обстоятельствах, при которых он не будет выполняться:

  • Если System.exit(0) вызывается; или,
  • если исключение генерируется вплоть до JVM и происходит поведение по умолчанию (т.е. printStackTrace() и выход)

Есть ли другие программные поведения, которые предотвратят выполнение кода в блоке finally{}? В каких конкретных условиях будет выполняться код или нет?

EDIT: Как указывало NullUserException, второй случай на самом деле не соответствует действительности. Я думал, это потому, что текст стандартной ошибки печатается после этого в стандартном формате, предотвращая просмотр текста без прокрутки.:) Извинения.

4b9b3361

Ответ 1

Если вы вызываете System.exit(), программа немедленно выйдет без вызова finally.

Сбой JVM, например. Ошибка сегментации также предотвратит окончательное вызванное. то есть JVM немедленно останавливается в этой точке и создает отчет о сбое.

Бесконечный цикл также предотвратит, наконец, вызов.

Блок finally всегда вызывается, когда бросается Throwable. Даже если вы вызываете Thread.stop(), который запускает ThreadDeath, который должен быть брошен в целевой поток. Это можно поймать (это Error), и будет вызываться блок finally.


public static void main(String[] args) {
    testOutOfMemoryError();
    testThreadInterrupted();
    testThreadStop();
    testStackOverflow();
}

private static void testThreadStop() {
    try {
        try {
            final Thread thread = Thread.currentThread();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    thread.stop();
                }
            }).start();
            while(true)
                Thread.sleep(1000);
        } finally {
            System.out.print("finally called after ");
        }
    } catch (Throwable t) {
        System.out.println(t);
    }
}

private static void testThreadInterrupted() {
    try {
        try {
            final Thread thread = Thread.currentThread();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    thread.interrupt();
                }
            }).start();
            while(true)
                Thread.sleep(1000);
        } finally {
            System.out.print("finally called after ");
        }
    } catch (Throwable t) {
        System.out.println(t);
    }
}

private static void testOutOfMemoryError() {
    try {
        try {
            List<byte[]> bytes = new ArrayList<byte[]>();
            while(true)
                bytes.add(new byte[8*1024*1024]);
        } finally {
            System.out.print("finally called after ");
        }
    } catch (Throwable t) {
        System.out.println(t);
    }
}

private static void testStackOverflow() {
    try {
        try {
            testStackOverflow0();
        } finally {
            System.out.print("finally called after ");
        }
    } catch (Throwable t) {
        System.out.println(t);
    }
}

private static void testStackOverflow0() {
    testStackOverflow0();
}

печатает

finally called after java.lang.OutOfMemoryError: Java heap space
finally called after java.lang.InterruptedException: sleep interrupted
finally called after java.lang.ThreadDeath
finally called after java.lang.StackOverflowError

Примечание: в каждом случае поток продолжал работать, даже после SO, OOME, Interrupted и Thread.stop()!

Ответ 2

Бесконечный цикл в блоке try.

Коррумпированная оперативная память? Программа больше не работает так, как написано? Я действительно отлаживал это однажды на машине DOS.

Ответ 3

Есть вероятность частичного выполнения, когда, наконец, сам генерирует исключение (или приводит к ошибке)

Ответ 4

Можно было бы: "A, наконец, является частью потока daeomon, он не может быть выполнен".

Ответ 5

Единственными моментами, которые окончательно не будут вызываться, являются:

если питание отключается

  • если вы вызываете System.exit()
  • если сначала сбой JVM
  • если в блоке try есть бесконечный цикл
  • Если питание отключается

Ответ 6

Тестирование блока finally в разных операциях в блоке try.

 public static void main(String [] args){

    try{
        System.out.println("Before Statement");
        /*** Statement ***/
        System.out.println("After Statement");
    }
    catch(Exception e){
    }
    finally{
        System.out.println("Finally is Executed");
    }

Заявления, в которых выполняется окончательный блок:

  • Thread.currentThread().interrupted();
  • Thread.currentThread().destroy();
  • Thread.currentThread().stop();
  • Thread.sleep(10);
  • Thread.currentThread().interrupt();
  • Runtime.getRuntime().addShutdownHook(Thread.currentThread());
  • Если возникло исключение.
  • Если нет исключения.

Заявления, в которых окончательный блок не выполняется:

  • Thread.currentThread().suspend();
  • System.exit(0);
  • JVM разбился.
  • Питание к чипу процессора отключается.
  • ОС убивает процесс JVM.
  • Runtime.getRuntime().exit(0);
  • Runtime.getRuntime().halt(0);

Ответ 7

Я думаю, что когда JVM неожиданно выходит из-за какой-либо причины, это может быть причиной того, что элемент управления не войдет в блок finally и никогда не выполнится.

Ответ 8

Вы можете сделать его частью Daemon Thread. Вы можете использовать метод setDaemon(boolean status), который используется для отметки текущего потока как потока потока или пользовательского потока и выхода из JVM по мере необходимости. Это позволит вам выйти из JVM до выполнения finally{}.

Ответ 9

Еще один возможный экземпляр блока finally, который никогда не выполнялся, был бы вызван конструкцией, в которой был введен метод, возвращенный перед блоком try, как и в случаях с очень плохим кодом, который я видел время от времени:

public ObjectOfSomeType getMeAnObjectOfSomeType() throws SomeHorrendousException {
    if (checkSomeObjectState()) {
        return new ObjectOfSomeType();
    }

    try {
        // yada yada yada...
    } catch (SomeHorrendousException shexc) {
        // wow, do something about this horrendous exception...
    } finally {
        // do some really important cleanup and state invalidation stuff...
    }

Я знаю, что никто из вас никогда не сделает этого, поэтому я не решался добавить это как возможный сценарий, но подумал, а в пятницу, что за черт; )