Чи можна вловити сигнал Ctrl+ Cу програмі командного рядка Java? Я хотів би очистити деякі ресурси перед тим, як припинити програму.
Відповіді:
Ви можете приєднати гачок відключення до ВМ, який запускається, коли ВМ вимикається:
Віртуальна машина Java вимикається у відповідь на два види подій:
Програма виходить нормально, коли виходить останній недемон-потік або коли викликається метод виходу (еквівалентно System.exit), або
Віртуальна машина припиняється у відповідь на переривання користувача, наприклад, набравши Ctrl+ C, або загальносистемну подію, наприклад, вихід із системи або вимкнення системи.
Потік, який ви передаєте як гачок відключення, повинен дотримуватися кількох правил, тому уважно читайте пов'язану документацію, щоб уникнути проблем. Сюди входить забезпечення безпеки ниток, швидкого закінчення нитки тощо.
Крім того, як зазначає коментатор Джеспер, гачки відключення гарантовано працюють при нормальному відключенні ВМ, але якщо процес ВМ припиняється примусово, вони цього не роблять. Це може статися, якщо рідний код випсується або якщо ви примусово вб'єте процес ( kill -9
, taskkill /f
).
Але в цих сценаріях усі ставки в будь-якому випадку не діють, тому я б не надто витрачав на це думки.
TerminateProcess()
або SIGKILL
), але це поза нормальною роботою, і оскільки Ctrl + C вже охоплений гачком відключення, використовувати його можна безпечно. Ви багато не можете зробити, якщо ОС у будь-якому випадку фактично припиняє ваш процес.
kill -HUP
є "найм'якшим" вбивством від Unix і має запустити гачок відключення. Не впевнений у замовчуванні kill
.
Тільки для швидкого тестування консолі ...
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
Thread.sleep(200);
System.out.println("Shutting down ...");
//some cleaning up code...
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
});
Верхня відповідь пропонує використовувати гачок відключення. Відключення гаків набагато більше проблем, ніж вони варті. Вони працюють у невизначеному порядку, і бібліотеки, від яких ви залежате, можуть додати власні гачки вимкнення, що може означати, що щось, від чого залежить ваш власний гак вимкнення, може бути деініціалізовано до того, як ваш гак вимкнення буде запущений. Збережіть собі головний біль та використовуйте обробник сигналів:
Signal.handle(new Signal("INT"), // SIGINT
signal -> System.out.println("Interrupted by Ctrl+C"));
Signal
В даний час sun.misc.Signal
це означає, що він буде застарілим - але те, на що його замінюють, наразі називається jdk.internal.misc.Signal
, тому, поки команда Java не з’ясує, як публічно виставляти обробники сигналів не внутрішньо, остерігайтеся, що цей дзвінок може зникнути. Поки що (на момент JDK 11), вона sun.misc.Signal
все ще існує.