Рубрики
Без рубрики

Runtime.getRuntime().halt() vs System.exit() в Java

Изучите различия между Runtime.getRuntime().halt() и System.exit() в Java.

Автор оригинала: Kamlesh Kumar.

1. Обзор

В этом уроке мы рассмотрим System.exit () , Runtime.getRuntime().halt () и то, как эти два метода сравниваются друг с другом.

2. Система.выход()

Метод System.exit() останавливает запущенную виртуальную машину Java . Но, прежде чем остановить JVM, он вызывает последовательность завершения работы , также известную как упорядоченное завершение работы. Пожалуйста обратитесь к этой статье , чтобы узнать больше о добавлении крючков выключения.

Последовательность завершения работы JVM сначала вызывает все зарегистрированные крючки завершения работы и ждет их завершения. Затем он запускает все незваные финализаторы, если включен параметр finalization-on-exit . Наконец, это останавливает JVM.

Этот метод, по сути, вызывает метод Runtime.getRuntime().exit() внутренне. Он принимает в качестве аргумента целочисленный код состояния и имеет тип возврата void :

public static void exit(int status)

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

3. Runtime.getRuntime().halt()

Класс Runtime позволяет приложению взаимодействовать со средой, в которой оно работает.

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

В отличие от метода exit , этот метод не запускает последовательность завершения работы JVM. Поэтому ни крючки выключения, ни финализаторы не выполняются при вызове метода halt .

Этот метод нестатичен и имеет аналогичную сигнатуру System.exit() :

public void halt(int status)

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

4. Пример

Теперь давайте рассмотрим пример методов exit и halt с помощью крючка shutdown.

Чтобы все было просто, мы создадим класс Java и зарегистрируем крюк выключения в блоке static . Кроме того, мы создадим два метода: первый вызывает метод exit , а второй-метод halt :

public class JvmExitAndHaltDemo {

    private static Logger LOGGER = LoggerFactory.getLogger(JvmExitAndHaltDemo.class);

    static {
        Runtime.getRuntime()
          .addShutdownHook(new Thread(() -> {
            LOGGER.info("Shutdown hook initiated.");
          }));
    }

    public void processAndExit() {
        process();
        LOGGER.info("Calling System.exit().");
        System.exit(0);
    }

    public void processAndHalt() {
        process();
        LOGGER.info("Calling Runtime.getRuntime().halt().");
        Runtime.getRuntime().halt(0);
    }

    private void process() {
        LOGGER.info("Process started.");
    }

}

Итак, чтобы сначала протестировать метод exit, давайте создадим тестовый случай:

@Test
public void givenProcessComplete_whenExitCalled_thenTriggerShutdownHook() {
    jvmExitAndHaltDemo.processAndExit();
}

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

12:48:43.156 [main] INFO com.baeldung.exitvshalt.JvmExitAndHaltDemo - Process started.
12:48:43.159 [main] INFO com.baeldung.exitvshalt.JvmExitAndHaltDemo - Calling System.exit().
12:48:43.160 [Thread-0] INFO com.baeldung.exitvshalt.JvmExitAndHaltDemo - Shutdown hook initiated.

Аналогично мы создадим тестовый случай для метода halt :

@Test
public void givenProcessComplete_whenHaltCalled_thenDoNotTriggerShutdownHook() {
    jvmExitAndHaltDemo.processAndHalt();
}

Теперь мы также можем запустить этот тестовый случай и увидеть, что крючок выключения не вызывается:

12:49:16.839 [main] INFO com.baeldung.exitvshalt.JvmExitAndHaltDemo - Process started.
12:49:16.842 [main] INFO com.baeldung.exitvshalt.JvmExitAndHaltDemo - Calling Runtime.getRuntime().halt().

5. Когда использовать выход и остановку

Как мы видели ранее, метод System.exit() запускает последовательность завершения работы JVM, в то время как метод Runtime.getRuntime().halt() резко завершает работу JVM.

Мы также можем сделать это с помощью команд операционной системы. Например, мы можем использовать SIGINT или Ctrl+C, чтобы вызвать упорядоченное завершение работы, например System.exit() и SIGKILL, чтобы внезапно убить процесс JVM.

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

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

Наконец, приложение может также ограничить эти методы от случайного использования. Оба этих метода вызывают метод checkExit класса SecurityManager . Таким образом, чтобы запретить exit и halt операции , приложение может создать политику безопасности с помощью класса SecurityManager и вызвать SecurityException из метода checkExit .

6. Заключение

В этом уроке мы рассмотрели методы System.exit() и Runtime.getRuntime().halt() с помощью примера. Кроме того, мы также говорили об использовании и лучших практиках этих методов.

Как обычно, полный исходный код этой статьи доступен на Github .