자바에서 Ctrl + C 잡기


81

자바 명령 줄 애플리케이션에서 Ctrl+ C신호 를 잡을 수 있습니까? 프로그램을 종료하기 전에 일부 리소스를 정리하고 싶습니다.

답변:


89

VM이 종료 될 때마다 실행되는 종료 후크 를 VM에 연결할 수 있습니다 .

Java 가상 머신은 두 가지 유형의 이벤트에 대한 응답으로 종료됩니다.

  • 데몬이 아닌 마지막 스레드가 종료되거나 종료 (동등하게 System.exit) 메소드가 호출 될 때 프로그램이 정상적으로 종료됩니다.

  • 가상 머신은 Ctrl+ 입력과 같은 사용자 인터럽트 C또는 사용자 로그 오프 또는 시스템 종료와 같은 시스템 전체 이벤트 에 대한 응답으로 종료됩니다.

하지만 종료 후크로 전달하는 스레드는 몇 가지 규칙을 따라야하므로 문제가 발생하지 않도록 링크 된 문서를주의 깊게 읽으십시오. 여기에는 스레드 안전성 보장, 스레드의 빠른 종료 등이 포함됩니다.

또한 논평자 Jesper가 지적했듯이 종료 후크는 VM이 ​​정상적으로 종료 될 때 실행되도록 보장되지만 VM 프로세스가 강제로 종료되면 실행되지 않습니다. 이는 네이티브 코드가 망가 졌거나 프로세스를 강제로 종료하는 경우 ( kill -9, taskkill /f) 발생할 수 있습니다 .

그러나 이러한 시나리오에서는 어쨌든 모든 베팅이 꺼져 있으므로 너무 많은 생각을 낭비하지 않을 것입니다.


1
모든 상황에서 종료 후크가 실행되는 것은 아닙니다. 실행되지 않는 상황이있을 수 있으므로 종료 후크에서 수행하는 작업에 따라 프로그램이 올바르게 작동하도록 만들지 마십시오.
Jesper

4
프로세스가 강제로 종료되면 ( TerminateProcess()또는 SIGKILL) 실행되지 않지만 정상적인 작업 이 아닐 때 Ctrl + C가 이미 종료 후크에 포함되어 있으므로 사용하는 것이 안전합니다. 어쨌든 OS가 실제로 프로세스를 종료하면 많은 일을 할 수 없습니다.
Joey

1
kill -HUPUnix에서 "가장 부드러운"킬 (kill)이며 종료 후크를 실행해야합니다. 기본값에 대해 잘 모르겠습니다 kill.
livefree75

1
기본 종료는 내 컴퓨터에서 종료 후크를 실행합니다 (Redhat 7.3). Kill -9는 그렇지 않습니다.
MikeKulls

2
종료 후크는 특정 순서로 실행되는 것이 보장되지 않으므로 종료 후크가 아직 실행되지 않은 다른 종료 후크에 의존하는 경우 (또는 그 반대의 경우) 문제가 발생할 수 있습니다.
Luke Hutchison

29

빠른 콘솔 테스트 목적으로 ...

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();
            }
        }
    });

0

가장 좋은 대답은 종료 후크 사용을 제안합니다. 셧다운 후크는 가치가있는 것보다 훨씬 더 많은 문제입니다. 그것들은 불확정 한 순서로 실행되며, 의존하는 라이브러리는 자체 종료 후크를 추가 할 수 있습니다. 즉, 종료 후크가 실행되기 전에 자체 종료 후크가 의존하는 항목이 초기화 해제 될 수 있습니다. 두통을 피하고 신호 처리기를 사용하십시오.

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여전히 존재합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.