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

В Java, является ли "окончательный" блок гарантированным называться (в основном методе)?

Я новичок в Java, и мне было интересно, если у меня есть следующий типичный Java-код

public class MyApp {
  public static void main(String[] args) {
    try {
      // do stuff
    } catch {
      // handle errors
    } finally {
      // clean up connections etc.
    }
  }
}

гарантирует ли JVM, что блок finally всегда будет запущен? Чтобы понять, откуда я, я привык к программам C/С++, которые могут просто сбой, если вы разыщите указатель NULL, и после этого вы не сможете запускать какой-либо код.

Но поскольку я понимаю Java и весь бизнес GC/управляемой памяти в целом, нет такой вещи, как разыменование нулевого указателя, все это захватывающее искушение, поэтому на самом деле для моей программы не может быть сбоя, что может сделать это пропустить наконец, или есть? Например, в Python я обычно делаю

try:
  # do stuff
except AnExceptionIKnewMightHappen:
  # react in an appropriate way
except:
  # log that weird error I had not known could happen

и у меня никогда не было никакого приложения, не проходящего через мой код.

Конечно, если ОС по какой-то причине убивает процесс (или если что-то убивает всю систему, например, потянув за вилку), то не так много может сделать Java. Кроме того, с PHP я знаю неустранимые ошибки, с которыми вы не можете защитить, даже несмотря на то, что интерпретатор все еще был там после того, как это произошло (по крайней мере, оно может выводить правильное сообщение).

Изменить: Просто для ясности (на самом деле это не было по-настоящему неправильно понято), позвольте мне добавить, что я искал вещи внутри своего кода, что может привести к тому, что в конечном итоге обойдется. Поэтому указание на System.exit было полезным напоминанием, хотя я не понимаю, почему я хотел бы сделать что-то подобное.

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

4b9b3361

Ответ 1

В принципе да, кроме примечания приведенного здесь (выделено мной):

Если JVM завершает работу во время выполнения кода try или catch, то окончательный блок может не выполняться. Аналогично, если поток выполнение кода try или catch прерывается или убивается, наконец, блок может не выполняться, хотя приложение в целом продолжается.

Ответ 2

Не гарантируется:

public class Main {
    public static void main(String args[]) {
        try {
            System.out.println("try");
            System.exit(0);
        } catch (Exception e) {
            System.out.println("exception");
        } finally {
            System.out.println("finally");
        }
    }
}

Запустите это.

Ответ 3

Одним словом, да.

Код в блоке finally в Java всегда выполняется, если:

  • JVM выходит во время блока try или catch
  • Поток, выполняющий код, прерывается или убивается во время блока try или catch.

(from: http://java.sun.com/docs/books/tutorial/essential/exceptions/finally.html)

Итак, если вы явно не вызываете System.exit(int) или не убиваете процесс или поток извне, вы можете положиться на него.

Ответ 4

Абсолютно, этот блок будет работать каждый раз. За исключением случая сбой JVM или вызываемой функции exit(). У меня был код, где приложение Java вызывало собственный код JNI, который был отключен. В результате авария уничтожила JVM и помешала окончательному запуску.

Ответ 5

Крис Камерон прав. Но обычно выполняется finally -block. Null pointer dereferece существует в Java:

try {
    List<Object> x = null;
    x.get(1); //throws the unchecked NullPointerException
} finally {
    //will be executed
}

Выполняется окончательный блок.

Ответ 6

Да, JVM всегда выполняет его. Gaurranteed.

Конечно... если сам JVM умирает (например: System.exit()), то он не в состоянии ничего выставить. Но умирание JVM не является проблемой внутри java.

Ответ 7

Erm, yep:) Будет ли ваш код попадать в catch или нет, наконец, он будет запущен. Это хорошее место для установки кода, который очищается после попытки.

Очевидно, что он не будет работать, если вы сломаете jvm:)

Ответ 8

Да, блок finally всегда будет запущен, если не произойдет сбой JVM (очень редко, но это может произойти).

Ответ 9

единственными исключениями, которые, наконец, блок не выполняется, являются либо сбои JVM, либо system.exit().

Ответ 10

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