Language/JAVA

java class loader #1

적외선 2016. 8. 4. 15:06

Java 동적으로 클래스를 로딩하기 때문에 런타임에 모든 코드가 JVM 링크됩니다모든 클래스는 해당 클래스가 참조되는 순간에 동적으로 JVM 링크되며메모리에 로딩됩니다자바의 런타임 라이브러리([jdk path]/jre/lib/rt.jar) 역시 예외가 아닙니다이러한 동적인클래스 로딩은 자바의 클래스로더 시스템을 통해서 이루어지며자바가 기본적으로 제공하는 클래스로더는 java.lang.ClassLoader 통해서 표현됩니다. JVM 시작되면부트스트랩(bootstrap) 클래스로더를 생성하고 다음에 가장 첫번째 클래스인 Object 시스템에 로딩합니다.
런타임에 동적으로 클래스를 로딩한다는 것은 JVM 클래스에 대한 정보를 갖고 있지 않다는 것을 의미함으로서 JVM 클래스에 대한정보를 알지 못합니다따라서클래스로더는 클래스를 로딩할  필요한 정보를 구하고 클래스가 올바른지를 검사해야 합니다.


Load-time dynamic loading and Run-time dynamic loading

클래스를 로딩하는 방식에는 로드타임 동적 로딩(load-time dynamic loading) 런타임 동적 로딩(run-time dynamic loading) 있습니다. 

  public class HelloWorld {
     public static void main(String[] args) {
        System.out.println("
안녕하세요!");
     }
  }

코드 1.


로드타임 동적 로딩은 하나의 클래스를 로딩하는 과정에서 동적으로 클래스를 로딩하는 것을 말합니다코드 1 HelloWorld 클래스를 실행하면, JVM 시작되고앞에서 말했듯이 부트스트랩 클래스로더가 생성된 후에모든 클래스가 상속받고 있는 Object 클래스를 읽어옵니다 이후에클래스로더는 명령행에서 지정한 HelloWorld 클래스를 로딩하기 위해 HelloWorld.class 파일을 읽습니다그리고HelloWorld 클래스를 로딩하는 과정에서 필요한 클래스 java.lang.String java.lang.System 읽어옵니다  클래스는 HelloWorld 클래스를 읽어오는 로드타임에 동적으로 로딩됩니다.

 

class HelloWorld1 implements Runnable {
     public void run() {
        System.out.println("
안녕하세요, 1");
     }
  }
  class HelloWorld2 implements Runnable {
     public void run() {
        System.out.println("
안녕하세요, 2");
     }
  }

  public class RuntimeLoading {
     public static void main(String[] args) {
        try {
           if (args.length < 1) {
              System.out.println("
사용법: java RuntimeLoading [클래스 이름]");
              System.exit(1);
           }
           Class klass = Class.forName(args[0]);
           Object obj = klass.newInstance();
           Runnable r = (Runnable) obj;
           r.run();
        } catch(Exception ex) {
           ex.printStackTrace();
        }
     }
  }

코드 2.

 

런타임 동적 로딩은 클래스를 로딩할 때가 아닌 코드를 실행하는 순간에 클래스를 로딩하는 것을 말합니다.


코드 2에서 Class.forName(className) 파리미터로 받은 className 해당하는 클래스를 로딩한 후에  클래스에 해당하는 로딩한 클래스의 인스턴스가 아닌 Class 인스턴스를 리턴합니다그리고 Class 클래스의 newInstance() 메소드는 Class 나타내는 클래스의 인스턴스를 생성합니다예를 들어코드 3 java.lang.String 클래스의 객체를 생성합니다.

  Class klass = Class.forName("java.lang.String");
  Object obj = klass.newInstance();

코드 3.


따라서, Class.forName() 메소드를 실행하는 클래스에서는 Class.forName() 실행되기 전까지는 어떤 클래스를 참조하는    없습니다.


ClassLoader

클래스로더를 사용하기 위해서는 보통의 자바 클래스처럼 해당하는 클래스의 객체를 생성하고 객체의 특정 메소드를 호출하면 됩니다또한상속을 받아 클래스로드를 커스터마이징  수도 있습니다.

자바의 클래스로더는 클래스로더 딜리게이션 모델(ClassLoader Delegation Model)으로서 부모 클래스로더가 먼저 클래스를 로딩하도록합니다특정 클래스로더 클래스를 읽어온 클래스로더(부모 클래스로더)에게 클래스 로딩을 요청하는 것입니다


그림 1. ClassLoader Delegation Model[1]


그림 1 클래스로더간의 관계를 보여주고 있습니다 경우, NetworkClassLoader(가정) JarFileClassLoader(가정) 로딩하고, JarFileClassLoader 클래스는 AppClassLoader 로딩하였음을 보여줍니다, JarFileClassLoader NetworkClassLoader 부모 클래스로더가 되고, AppClassLoader JarFileClassLoader 부모 클래스로더가 되는 것입니다.

<자바에서 기본으로 제공하는 부트스트랩클래스로더 등에 관한 설명은 [2-3] 보면   있습니다.>


References

 

[1] http://javacan.tistory.com/3

[2] http://blog.naver.com/PostView.nhn?blogId=choigohot&logNo=40192701035

[3] http://javacan.tistory.com/entry/2