오늘은 어디로 갈까...

ClassLoader 본문

낙서

ClassLoader

剛宇 2009. 3. 26. 11:52

 클래스 재반영(reload).
 누구나 한번쯤 생각해 본적이 있을것이다. VM을 종료시키지 않고 변경된 클래스를 반영하는 일. 아 생각만해도 행복하다. ^^;
다년간 삽집을 통해 얻어낸것이라고는 클래스는 재반영(reload)이 안된다는 사실...
(이 지식을 습득한 시점이 2002년도였으므로 지금은 어떤지 확실히 모르겠고, 이 글이 거짓말로 도배된것일 수 있으니 주의바란다.)
 그럼 많은 J2EE Application Server에서 지원하는 hot deployment 기능은 뭐란 말인가?
 그 베일을 벗겨보면, 클래스를 재반영하는것이 아니라, 클래스로더를 바꿔치기 해서 재반영된것처럼 보이게 하는것이다. 클래스는 클래스로더에 의해서 적재된다. 그래서 사용하는 클래스로더를 바꾸면 새로운 클래스가 로딩되는것이다.

 자바 1.2부터는 로딩 요청을 부모에게 전달하는 방식의, 클래스로더 위임 모델(ClassLoader Delegation Model)을 사용한다. 즉, Parent First  방식이다. 클래스를 로딩하도록 요청받으면 캐시에 저장된 클래스가 있을 경우 그 클래스를 반환하고, 없을 경우는 부모 클래스로더에게 해당 클래스를 요청하는 것이다. 만약 부모 클래스로더도 해당 클래스가 없다면, 자신의 영역(?)에서 클래스를 찾아서 로딩하고 없다면 ClassNotFoundException을 발생시키는것이다.
즉 정리하자면, loadClass() -> findLoadedClass() -> Parent ClassLoader.loadClass() -> findClass() -> defineClass() 정도 되겠다.

    protected synchronized Class loadClass(String name, boolean resolve)
			throws ClassNotFoundException {
		// First, check if the class has already been loaded
		Class c = findLoadedClass(name);
		if (c == null) {
			try {
				if (parent != null) {
					c = parent.loadClass(name, false);
				} else {
					c = findBootstrapClass0(name);
				}
			} catch (ClassNotFoundException e) {
				// If still not found, then invoke findClass in order
				// to find the class.
				c = findClass(name);
			}
		}
		if (resolve) {
			resolveClass(c);
		}
		return c;
	}

그래서 간단한(?) Custom ClassLoader를 만들때 loladClass()를 오버라이드(override)하는게 아니라, findClass()를 오버라
이드하는것이다.


자, 그럼 가장 기본적인 클래스 로더에 대해 알아보자. 자바가 실행되면 기본적으로 세개의 클래스로더가 생성된다.
      Bootstrap Class Loader
                 |
      Extention Class Loader
                 |
     Application Class Loader
                 |
       --+-------+-------+--
         |               |
       Custom          Custom
     ClassLoader     ClassLoader


BootstrapClassLoader : VM의 네이티브 코드 영역에 존재하면 Object같은 코어 자바 클래스를 로딩한다. 즉, rt.java 같은 Runtime 클래스들이나, i18n.jar같은 국제화 클래스들을 로딩한다. 자바 코드로는 접근이 불가능하다. (sun.boot.class.path)

ExtClassLoader : 확장 클래스들을 로딩한다. 즉, JRE의 lib/ext 디렉토리에 있는 JAR 파일들을 로딩한다. (java.ext.dirs)
AppClassLoader : 클래스패스에 잡혀있는 클래스와 JAR파일을 로딩한다. System Property에 있는 java.class.path로 설정한 값(기본값을 현재 디렉토리를 나타내는 .이다), 실행 옵션(command-line options)인 -classpath 또는 -cp 환경변수에 잡혀있는 CLASSPATH가 되겠다. 실행 옵션은 환경변수인 CLASSPATH를 덮어씌워버린다.

재미있는것은... 아니 당연할지도 모르겠지만, 자식은 부모의 클래스를 사용할 수 있지만, 부모는 자식의 클래스를 사용할 수 없다. 그리고 이웃한(?) 클래스로더들도 서로의 클래스를 사용할 수 없다.

JVM classpath 관련 옵션
    -Xbootclasspath:<directories and zip/jar files separated by ;>
                    Bootstrap 클래스와 자원(resource) 검색 경로를 설정한다.
    -Xbootclasspath/a:<directories and zip/jar files separated by ;>
                      bootstrap class path 뒤에 경로를 추가한다.
    -Xbootclasspath/p:<directories and zip/jar files separated by ;>
                      bootstrap class path 앞에 경로를 추가한다.

일반적으로 -Xbootclasspath 이 옵션은 구경하기 힘들다. 자주 애용되는 용도가, JVM Layer에서 라이브 객체, 메모리/컬렉션 추척 등등~ 한마디로 말해 모니터링~~하기 위해 수정한 놈들을 추가해주기 위함이다.
무식하게 생각해보자. 자바의 모든 객체는 java.lang.Object를 부모로 두고 있다. 이 Object 클래스를 손보면 원하는 결과를 받을 수 있을거 같이 않는가? 믿거나 말거나~~~~~~~~~~~~


참고 :
http://www.javaworld.com/javaworld/jw-03-2000/jw-03-classload.html?page=1
http://java.sun.com/docs/books/tutorial/deployment/jar/apiindex.html