SSISO Community

시소당

Shutdown Hook 작성 방법 및 샘플

시스템의 비정상종료시에(Ctrl+C) 애플리케이션이 무언가 처리후 종료되어야 할 경우 그 방안에 대하여 작성할 수 있는 방법과 샘플코드를 보여주도록 한다.

이 번 아티클에서는 shutdown hook에 대한 글을 써보고자 한다. 우선 개요부터 말하자면 당신이 열나게 애플리케이션을 만들었다고 가정을 해보자. 사용자가 도스창에서 애플리케이션을 실행시키고 동작시키고 있는데, 이 사용자가 갑자기 이게 아니다 싶어서 애플리케이션을 죽이려고 한다. 근데 분명 내가 메뉴에 종료라는 항목을 하나 추가해주었거늘.. Ctrl+C를 눌러버리고야 말았다.

문제는 무었인고? 나는 해당사용자의 내용에 대한 backward기능을 주고 싶어서 그 사람이 하고 있는 행동에 대한 rollback가능한 로그를 쌓고 사용자가 애플리케이션을 종료시키면 그때 필요없는 데이터들을 모두 없애버리리라 마음을 먹고 있던 차였다.

그런데...

위의 같은 상황이 발생을 한다면 당신은 어떻게 할것인가?
서 블릿 컨테이너나 Applet의 경우도 실제 라이프사이클에 의하여 동작하여 해당 클래스가 메모리에서 unload되어지는 시점에 destroy메소드들을 호출하도록 하고 있는데, 위의 ctrl+c라는 행위는 아예 daemon thread까지 "너 죽어랏~!" 하면서 보내버리는 케이스니 말이다.

만약 저러한 애플리케이션을 스윙으로 만든다면 actionPerformed 이벤트를 걸어서 어떻게든
처리를 하겠는데 일반 text based application의 경우는 더더욱이 문제가 아닐듯 싶다.

▶ 자바에서의 shutdown event의 두가지

자바에서 virtual machine이 shutdown을 인식하는 방법으로는 두가지가 있는데

1. 첫번째로는 애플리케이션이 System.exit()메소드를 통하여 정상적으로 종료하는 경우가 있고,
2. 두번째로는 사용자가 직접 Ctrl+C를 키보드에 입력함으로서 현재 실행중인 애플리케이션을
closing하지 않고 virtual machine을 비정상적으로 강제종료시키는 경우이다.

간단하게 shutdown hook을 작성할 수 있는 방법은 다음과 같다.

1. java.lang.Thread를 상속받는 클래스를 하나 작성한다.
2. Thread의 run메소드를 구현할 때 당신이 shutdown시에 처리해야 할 일들에 대하여 기술한다.
3. 해당 shutdown hook클래스를 생성한다.
4. Runtime클래스의 addShutdownHook()메소드를 이용하여 등록한다.
    Runtime.getRuntime().addShutdownHook(shutdownHook);

▶ ShutdownHook Sample정의

여기서 우선 애플리케이션을 만들 경우를 가정하자.
보통의 서블릿 컨테이너는 사용자에 대한 세션을 자신의 로컬파일로 저장하여 관리하고 있다.
레 진같은 엔진을 보더라도 session이라는 디렉토리에 file serialize를 통하여 저장하고 엔진이 종료되거나 세션의 시간이 만료되게 되면 그 저장된 temporary파일들을 삭제하는 루틴을 가지고 있다. 그런데 만약에 그러한 엔진들이 비정상적인 종료에 해당 파일들을 삭제하지 못하고 쌓아두게 된다면, 또한 접속이 많은 그러한 서버였다면 파일시스템의 사이즈가 비대하게 불어나게 될 것은 불을 보듯 뻔한 일 아닌가?

놀새~의 샘플코드 가정을 비슷하다.
애플리케이션이 시작되면 사용자의 고유식별파일을 하나 만들어서 기록하고 있다가 어떠한 방법으로라도 프로그램이 종료되게 되면 그 파일을 삭제하도록 할것이다.

자 그럼 위의 순서에 의하여 하나하나 작성을 해보도록 하자.

▶ ShutdownHookDemo.java

import java.io.*;

    public class ShutdownHookDemo {
    private String dir = ".";
    private String filename = "session_tmp.txt";

    /**
    *  애플리케이션이 시작되면 shutdown을 생성한후 등록한다.
    */
    public void start() {
        System.out.println("Demo");
        ShutdownHook shutdownHook = new ShutdownHook();
        Runtime.getRuntime().addShutdownHook(shutdownHook);
    }

    /**
    *  1. 실행의 순서는 먼저 tempoary파일의 생성
    *  2. Runtime클래스에 shutdown hook을 등록
    *  3. 사용자의 입력을 기다림(무한루프)
    */
    public static void main(String[] args) {
        ShutdownHookDemo demo = new ShutdownHookDemo();
        demo.setup();
        demo.start();

        try {
            while(true){
                System.in.read();
            }
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
    /**
    * ShutdownHook클래스를 inner클래스로 사용함으로서 ShutdownHookDemo클래스의
    * 멤버변수에 대한 참조를 가능하도록 만든다.
    */
    private class ShutdownHook extends Thread {
        public void run() {
            shutdown();
        }
    }

    /**
    *  Shutdown의 되는 시점에 생성되었던 temporary파일을 삭제한다.
    */
    private void shutdown() {
        System.out.println("start shutdown progress.. please wait");
        // delete the temp file
        File file = new File(dir, filename);

        if (file.exists()) {
            System.out.println("Deleting temporary file.");
            file.delete();
        }

    }
    /**
    *  프로그램최초 수행시에 임시파일을 생성해낸다.
    */
    private void setup(){
    // create a temp file
        File file = new File(dir, filename);

        try {
            System.out.println("Creating temporary file");
            file.createNewFile();
        }
        catch (IOException e) {
            System.out.println("Failed creating temporary file.");
        }
    }


    }


위에서 별반 다르게 볼건 없다. 프로그램이 시작되면

            while(true){
                System.in.read();
            }

처럼 무한루프를 돌며 사용자의 키보드 입력을 기다리게 되는데, ctrl+c가 입력되기 전에는 계속 입력만을 받게 된다.

실제 shutdown hook클래스는 아래와 같이 간단하게 만들수 있으며

    private class ShutdownHook extends Thread {
        public void run() {
            shutdown();
        }
    }

단순히 클래스가

    Runtime.getRuntime().addShutdownHook(shutdownHook);

에 의하여 등록만 되어 있으면 자동으로 처리되게 된다.


실 제로 테스트를 해볼경우 프로그램을 수행시키는 시점에 session_tmp.txt파일이 디렉토리에 생기게 된다. 계속 테스트하다가 실제 ctrl+C를 키보드에 입력했을 경우 shutdown progress라는 메시지와 함께 해당 임시파일은 없어지게 될것이다.

간단하게 테스트 해볼 수 있으며 위의 프로그램을 조금만 응용해도 당신은 아주 훌륭한 애플리케이션을 만들수 있을 것이다.

출처 : http://www.javapattern.info/?page=4

633 view

4.0 stars