Автор оригинала: 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 .