[java] 자바에서 Ctrl + C 잡기

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



답변

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

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

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

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

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

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

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


답변

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

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


답변