В Java гарантированно вызывается блок "finally" (в основном методе)? - PullRequest
22 голосов
/ 05 февраля 2009

Я новичок в 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 / 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 и приложение продолжают работать, было очень полезным, потому что, хотя мне это и сейчас кажется очевидным, я не думал об этом.

Ответы [ 10 ]

44 голосов
/ 05 февраля 2009

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

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

12 голосов
/ 05 февраля 2009

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

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

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

9 голосов
/ 05 февраля 2009

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

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

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

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

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

4 голосов
/ 05 февраля 2009

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

2 голосов
/ 05 февраля 2009

Крис Кэмерон прав. Но обычно выполняется finally -блок. Разыменование нулевого указателя существует в Java:

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

Блок finally выполняется.

1 голос
/ 06 февраля 2009

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

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

0 голосов
/ 02 марта 2017

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

0 голосов
/ 01 ноября 2010

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

0 голосов
/ 05 февраля 2009

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

0 голосов
/ 05 февраля 2009

Э-э-э, да :) Независимо от того, входит ваш код в зацепку или нет, в конечном итоге будет выполняться. Это хорошее место для размещения кода, который очищается после попытки.

Очевидно, что он не запустится, если вы сломаете jvm:)

...