[java] Javassist를 사용하여 핫스왑 구현

자바 개발을 하다보면 소스 코드를 수정하고 다시 컴파일해야하는 번거로움이 있습니다. 특히 서버 인스턴스를 다시 시작해야하는 경우, 개발 속도에 지장을 주는 경우가 많습니다. 이러한 문제를 해결하기 위해 핫스왑(Hotswap)이라는 개념을 사용할 수 있습니다. 핫스왑이란, 실행 중인 애플리케이션의 소스 코드를 수정하고, 수정된 코드를 즉시 반영하여 애플리케이션을 재시작하지 않고도 변화를 확인할 수 있는 기능을 말합니다.

이번 포스트에서는 Javassist라는 라이브러리를 사용하여 핫스왑을 구현하는 방법에 대해 알아보겠습니다.

Javassist란?

Javassist는 자바 소스 코드 조작을 위한 라이브러리로, 바이트 코드를 동적으로 수정하여 프로그램의 동작을 변화시킬 수 있습니다. 이는 리플렉션(Reflection)과 비슷한 기능을 제공하지만, 리플렉션보다 간편하게 사용할 수 있는 장점이 있습니다.

Javassist를 사용한 핫스왑 구현 방법

  1. Javassist 라이브러리를 프로젝트에 추가합니다. 다음은 Maven 기반 프로젝트의 경우, pom.xml 파일에 의존성을 추가하는 예시입니다.
<dependencies>
    <!-- other dependencies -->
    <dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.27.0-GA</version>
    </dependency>
    <!-- other dependencies -->
</dependencies>
  1. 핫스왑할 클래스를 작성합니다. 예를 들어, 다음과 같은 간단한 클래스를 작성해보겠습니다.
public class HelloWorld {
    public void sayHello() {
        System.out.println("Hello World!");
    }
}
  1. 핫스왑을 원하는 메소드를 수정합니다. 이 예시에서는 sayHello 메소드의 출력 내용을 변경해보겠습니다.
public class HelloWorld {
    public void sayHello() {
        System.out.println("안녕하세요, 세계!");
    }
}
  1. 핫스왑을 수행하는 코드를 작성합니다. Javassist를 사용하여 클래스 파일을 수정하고, 수정된 클래스를 로딩하여 반영하는 과정입니다. 아래의 코드는 이러한 과정을 수행하는 예시입니다.
import javassist.*;

public class HotSwapDemo {
    public static void reloadClass(String className) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get(className);
        cc.defrost();
        cc.writeFile();
        cc.detach();
    }
    
    public static void main(String[] args) throws Exception {
        // 핫스왑 대상 클래스의 경로와 이름을 정확히 입력해주세요.
        String className = "com.example.HelloWorld";
        
        // 클래스 파일 수정
        reloadClass(className);
        
        // 수정된 클래스 로딩
        Class<?> clazz = Class.forName(className);
        
        // 인스턴스 생성 및 메소드 호출
        Object instance = clazz.newInstance();
        clazz.getMethod("sayHello").invoke(instance);
    }
}
  1. 프로그램을 실행하고 핫스왑을 확인합니다. HelloWorld 클래스의 sayHello 메소드가 수정된 내용으로 출력되어야 합니다.

위와 같이 Javassist를 사용하여 핫스왑을 구현하는 방법을 알아보았습니다. Javassist를 이용하면 런타임 시 클래스 파일을 동적으로 수정할 수 있으므로, 개발 속도를 향상시킬 수 있습니다.

더 자세한 내용은 Javassist 공식 문서를 참고하시기 바랍니다. Javassist 공식 문서