Как использовать System.exit с аргументом в Java
Что проверяют
Знаете ли вы, что аргумент System.exit это код возврата процесса, который читает внешний мир: shell, CI, оркестратор. Следом обычно спрашивают, выполнится ли finally после вызова и почему System.exit не место в коде веб-приложения.
Как отвечать
System.exit(int status) делегирует в Runtime.getRuntime().exit(status) и никогда не возвращает управление обычным образом. Что стоит сказать про сам код:
- 0 означает успех, любое другое значение ошибку. Внятная практика: 1 для общей ошибки, 2 для неверных аргументов, свои коды для разных причин, чтобы скрипт мог их различить;
- диапазон: в Linux и macOS родитель видит только младшие 8 бит, поэтому
System.exit(-1)превращается в 255, аSystem.exit(256)в 0; - где его видно:
$?в shell, статус шага в CI, код завершения контейнера. Для сравнения, 137 и 143 это 128 плюс номер сигнала: 9 для SIGKILL и 15 для SIGTERM.
Что происходит при вызове: запускаются shutdown hooks из Runtime.addShutdownHook, затем JVM останавливается вместе со всеми потоками, включая не-демоны. Блоки finally в текущем потоке уже не выполнятся. Runtime.halt() останавливает JVM ещё жёстче, без хуков. А вызов System.exit изнутри shutdown hook просто зависнет.
Хорошая архитектура: вызывать exit в одном месте, на верхнем уровне, например System.exit(run(args)), где run возвращает код. В Spring Boot для этого есть ExitCodeGenerator и SpringApplication.exit(context). Если main завершился необработанным исключением, код и так будет 1, отдельный вызов не нужен.
Где спотыкаются
Вызывают System.exit из библиотеки, сервиса или веб-приложения. В сервлет-контейнере это останавливает весь сервер, а не один запрос.
Уверены, что finally отработает и закроет ресурсы. Не отработает, закрывать нужно через shutdown hook или до вызова.
Пишут тесты на код с System.exit. SecurityManager, через который такие вызовы раньше перехватывали, объявлен устаревшим в Java 17 и отключён в новых версиях JDK, так что тест просто убьёт JVM. Выход: выносить логику в метод, возвращающий код, и тестировать его.