본문 바로가기

Java

URLClassLoader를 사용 한 class hot deploy (실패)

Jrebel을 알게 되면서
class를 hot deploy 하는 방법이 뭘까... 하고서 찾아보았다.

classloader가 한번 class를 load하게 되면 그 클래스를 unload 할 수 없기 때문에
URLClassLoader를 사용해서 classloader를 새로 생성하여
class를 동적으로 로딩하면 가능하다라는 것을 알게 되어서
막 코딩을 시작. -_-

public class Reloader {
    private Log logger = LogFactory.getLog(Reloader.class);

    URLClassLoader appClassLoader = null;
    File dir = new File("C:/TDPWrokspace/test/bin/hotdeploy/");


    public void run() throws Exception {
        URL url = dir.toURL();
        URL[] urls = new URL[]{url};

        while(true) {
            Thread.sleep(2000);

            this.appClassLoader = new URLClassLoader(urls);
            Class appClass = this.appClassLoader.loadClass("hotdeploy.BaseDomain");
            Method printName = appClass.getMethod("printName", null);

            Object appInstance = appClass.newInstance();
            System.out.println(appInstance);
            printName.invoke(appInstance, null);
        }
    }
}

eclipse에서 급하게 실행을 해보았으나 당연히 실패 -_-

원인은... 분명 classloader는 매번 새로 생성해주고 있으나
동적으로 바꿔치고 싶은 hotdeploy.BaseDomain은 Classpath에 위치한 녀석이고
System classpath classloader에 의해 로딩 된 클래스라는거지....

그렇기 때문에 백날 저기서 URLClassLoader를 새로 만들어봐야..
URLClassLoader는 자기 상위에 있는 System-classpath classloader에게 클래스 로딩을 위임하기 때문에
아무 상관이 없다는거....(실제로 URLClassLoader가 참조하고 있는 디렉토리를 "ddd"로 바꿔도
실행은 잘~~~~ 된다.)

 흑.. 그리고 저렇게 매번 classloader를 새로 만들어내면
성능에도 문제가 생기지 싶다.

그렇다면..
클래스패스에 있는 클래스를 동적으로 로딩하려면...?

google을 이용해보니 classloader를 상속 받아서 클래스로더의 loadClass 메서드를 재정의 해서
사용하는 법이 있었는데, 수정 된 class 파일 자체를 stream으로 읽어와서 defineclass 메서드를 통해서
변경된 내용을 다시 classloader에 적재하는 방법이 있었다....

그렇게까지 해서 쓸건 아닌거 같고..


아무튼...
내가 생성한 classloader를 통해 클래스를 로드하고
동적으로 로딩하고 있는 클래스들을 내가 생성한 classloader를 통해 load해야
위와 같은 방법으로 해당 클래스를 동적으로 변경된 내용을 적용 할 수 있다는 얘기인 것 같다.

내일 다시 생각해봐야지..