'classloader'에 해당되는 글 3건

  1. 2009.11.30 [JAVA] 클래스 hot deploy #2
  2. 2009.11.05 URLClassLoader를 사용 한 class hot deploy (실패) (2)
  3. 2008.05.26 [Java] ClassLoader 경로 문제
라고 하기까진 뭐하고...
그냥 classloader를 바꿔버리는 것을 이용해서 해보았다.

예전에 실패했을 때의 원인이었던것...
(http://devyongsik.tistory.com/274)

기본적으로 클래스패스에 있던 클래스는
이미 시스템클래스로더가 클래스를 로딩한 상태이기 때문에
그 하위 클래스로더에서 아무리 URLClassLoader를 사용해 바꿔치기 해봤자
영향이 없다는 것...

그렇다면, 방법은..
우리가 hot deploy를 해보고 싶은 클래스를 시스템 클래스로더가 아닌
우리가 정의한 (즉, 우리가 컨트롤 할 수 있는) 클래스로더가 물고 올라가도록 하면
이후에도 우리가 컨트롤 할 수 있지 않을까... 생각했다.

이클립스에서 workspace를 c: 쪽을 사용하고 있는데
일단 이런저런 생각하기가 귀찮아서..
그냥 hot deploy의 대상이 되는 BaseDomain이라는 클래스를
d: 드라이브에 넣고, URLClassLoader를 사용해서 그 클래스를 로딩하도록 구현해봤다.




이렇게 실행하면 d: 에 있는 BaseDomain.class를 물고 올라간다.

이제, 다른 프로젝트던 어디서든..BaseDomain.java의 내용을 바꾸고
컴파일 한 후 위 Main이 돌고 있는 상태에서 새로 컴파일한 class를 D:에 넣어주면
새롭게 컴파일 된 내용으로 콘솔에 내용이 찍힌다.

오호라..~ 이게 되네?

하지만, 이걸 실제 어떻게 구현해서 써보려고 하면..
클래스로더가 하나의 클래스를 로딩하고 있는 상태도 아니고..
클래스가 바뀔 때마다 클래스로더 전체를 내렸다가 다시 생성하고 클래스를 다시 로딩하는 것은
상당히 비효율적이라는 생각이 좀 든다.. .. 아니 비효율이 문제가 아니라 다른 클래스들은 어떻게 되는겨..

그래서 다른 사이트에서 보면
URLClassLoader를 상속받아
새롭게 ClassLoader를 정의해서 .class의 바이트코드를 읽어와
defineClass() 메서드를 사용해서 그 클래스만 다시 로딩하는 방법으로 구현 된 것도 있었다.
(http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html)

처음 위 내용 봤을 때는 저렇게까지 해야하나 싶었는데..
생각해보니 안 그럼 낭비가 좀 있을 것 같다...

eclipse4j님이 알려주신 jrebel의 작동 방식도
자기만의 work디렉토리로 모니터링 대상이 되는 클래스들을 모두 옮긴 후
자기가 정의한 클래스로더로 그 클래스들을 전부 로딩한다고 한다. 겉으로 보기엔 상당히 엣지 있는데
속으로는 저런 일을 하고 있었다는 거.... ㅎㅎ

암튼...
세련스럽지는 않지만
해보고 싶은건 결국 해봤다 -_-;;;

근데 난 왜 이걸 그렇게 해보고 싶어했던걸까....-_-ㅋ


Posted by 용식
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해야
위와 같은 방법으로 해당 클래스를 동적으로 변경된 내용을 적용 할 수 있다는 얘기인 것 같다.

내일 다시 생각해봐야지..
Posted by 용식
출처 It is a time to run!!! | 왕언니
원본 http://blog.naver.com/johnrivelt/100045094537
Posted by 용식