Когда мы должны позвонить в систему.выход на Java



в Java, какая разница с или без System.exit(0) в следующем коде?



public class TestExit
{
public static void main(String[] args)
{
System.out.println("hello world");

System.exit(0); // is it necessary? And when it must be called?
}
}


The документ говорит: "Этот метод никогда не возвращает."Что это значит?

956   10  

10 ответов:

System.exit() можно использовать для запуска выключение крючки перед завершением программы. Это удобный способ обработки выключения в больших программах, где все части программы не могут (и не должны) знать друг о друге. Тогда, если кто-то хочет уйти, он может просто позвонить System.exit(), и крючки выключения (если правильно настроить) позаботятся о выполнении всех необходимых церемоний выключения, таких как закрытие файлов, освобождение ресурсов и т. д.

"этот метод никогда не возвращает." означает только, что метод не вернется; как только поток идет туда, он не вернется.

другой, возможно более распространенный, способ выйти из программы-это просто дойти до конца main метод. Но если есть какие-либо не-демонические потоки, они не будут закрыты, и поэтому JVM не выйдет. Таким образом, если у вас есть такие не-демонические потоки, вам нужны некоторые другие средства (кроме крючков выключения), чтобы закрыть все не-демонические потоки и освободить другие ресурсы. Если нет другие не-демонические потоки, возвращающиеся из main выключит JVM и вызовет крючки выключения.

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

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

когда документы говорят, что метод никогда не возвращается нормально, это означает, что следующая строка кода эффективно недоступно, хотя компилятор этого не знает:

System.exit(0);
System.out.println("This line will never be reached");

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

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

System.exit(0) завершает работу JVM. В простых примерах, подобных этому, трудно понять разницу. Параметр передается обратно в ОС и обычно используется для указания ненормального завершения (например, какая-то фатальная ошибка), поэтому, если вы вызвали java из пакетного файла или сценария оболочки, вы сможете получить это значение и получить представление о том, было ли приложение успешным.

это будет иметь большое влияние, если вы позвонили System.exit(0) в приложении, развернутом на сервере приложений (подумайте об этом, прежде чем попробовать).

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

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

System.exit(42);

кто будет использовать ваш код выхода? Сценарий, который вызвал приложение. Работает в Windows, Unix и всех других скриптах окружающая среда.

зачем возвращать код? Чтобы сказать такие вещи, как" мне не удалось","база данных не ответила".

чтобы узнать, как получить значение кода выхода и использовать его в сценарии оболочки unix или сценарии cmd windows, вы можете проверить этот ответ на этом сайте!--11-->

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

я обрабатываю это в своем коде следующим образом:

public static void exit(final int status) {
    new Thread("App-exit") {
        @Override
        public void run() {
            System.exit(status);
        }
    }.start();
}

никогда не следует вызывать систему.выход(0).

  1. это скрытый "goto", и" goto " нарушает поток управления. Полагаться на крючки в этом контексте-это ментальное отображение, о котором должен знать каждый разработчик в команде.
  2. выход из программы "нормально" обеспечит тот же код выхода для операционной системы, что и система.выход(0). Так что это излишне. Если ваша программа не может выйти "нормально", ваше развитие вышло из-под контроля. Вы должны всегда иметь полный контроль над состояние системы.
  3. вы скрываете проблемы программирования, такие как запуск потоков, которые обычно не останавливаются.
  4. Это относится к 3.: Вы можете столкнуться с непоследовательным состоянием приложения, прерывающим потоки ненормально.

кстати: возврат других кодов возврата, чем 0, имеет смысл, если вы хотите указать ненормальное завершение программы.

Спецификация Языка Java говорит, что

Выход Из Программы

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

все потоки, которые не являются потоками демона прекращать.

какой-то поток вызывает метод exit класса Runtime или class система, и операция выхода не запрещена менеджером безопасности.

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

хотя ответ был очень полезным, но некоторые, как он пропустил некоторые дополнительные детали. Я надеюсь, что ниже поможет понять процесс выключения в java, в дополнение к ответу выше:

  1. в упорядоченном * выключении JVM сначала запускает все зарегистрированные крючки выключения. Крючки завершения работы-это неустановленные потоки, зарегистрированные в среде выполнения.addShutdownHook.
  2. JVM не дает никаких гарантий на порядок отключения крючки запускаются. Если какие-либо потоки приложений (демон или nondaemon) все еще работают во время выключения,они продолжают работать одновременно с процессом выключения.
  3. когда все крючки выключения завершены, JVM может выбрать для запуска финализаторов если runFinalizersOnExit истинно, а затем останавливается.
  4. JVM не пытается остановить или прервать любые потоки приложений, которые все еще работают во время завершения работы; они резко прекращаются, когда JVM в конечном итоге останавливается.
  5. Если shutdown крючки или финализаторы не завершаются, тогда процесс упорядоченного выключения "зависает", и JVM должен быть внезапно выключен.
  6. при резком выключении JVM не требуется делать ничего, кроме остановки JVM; крючки выключения не будут работать.

PS: JVM может закрыться в любом аккуратность или крутой порядке.

  1. упорядоченное завершение работы инициируется, когда последний" нормальный " (nondaemon) поток завершается, кто-то вызывает Система.выход или с помощью других средств, специфичных для платформы (например, отправка SIGINT или нажатие Ctrl-C).
  2. пока выше стандартный и предпочитаемый путь для JVM для завершения работы, он также может быть отключен резко, вызвав Runtime.стой или убив процесс JVM через операционную систему (например, отправив SIGKILL).

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

поэтому, не используйте систему.выйдите, если вы хотите иметь возможность управлять своей программой из другой программы java в той же JVM.

Системы Использовать.выход, если вы хотите закрыть полный JVM нарочно и если вы хотите воспользоваться возможностями, которые были описаны в других ответах (например, выключить крючки:Java shutdown hook, ненулевое возвращаемое значение для командной строки: как получить статус выхода программы Java в Windows пакетный файл).

Также посмотрите на исключения времени выполнения:

Comments

    Ничего не найдено.