[java] ClassLoader
클래스로더라는 게 있단다. 프로그램에서 new라던지, 객체를 사용할 때 클래스를 적재하고 객체를 생생해 주는 일을 하는 것 같다. JVM이 기본적으로 부트스트랩이라는 클래스로더를 가지고 있으며 상속을 이용해 나름대로의 클래스로더를 구현할 수 있다고 한다.
아래는 j2se1.4 API doc의 ClassLoader의 내용이다.
클래스 로더는 클래스를 적재(load)하는 역할을 하는 객체이다. classloader 클래스는 추상클래스이다. 클래스의 이름을 받으면 클래스로더는 해당 클래스에 대한 정의를 구성하는 데이터를 찾거나 생산하려고 시도할 것이다. 전형적인(정해진?) 전략은 받은 이름을 파일 이름으로 바꾸고 나서 클래스의 이름에 해당하는 “class file”을 파일시스템으로부터 읽는다.
모든 클래스 객체는 자신을 정의한 ClassLoader에 대한 참조를 가지고 있다.
array 클래스의 Class객체는 class loader에 의해서 생성되지 않고 자바 런타임에 의해 요구되어질 때마다 자동적으로 생성된다. array 클래스에 Class.getClassLoader()를 실행하면 배열 요소 타입에 해당하는 클래스 로더가 리턴된다. 배열의 요소가 원시형이면 해당 배열 클래스는 클래스 로더가 없다.
응용프로그램은 자바 VM이 동적으로 클래스를 로드하는 방식을 확장하기 위한 목적으로 ClassLoader의 하위클래스를 구현한다.
클래스 로더는 보통, 보안 도메인을 지정하기 위하여 보안 관리자들에 의해 사용된다.
ClassLoader는 클래스와 자원들을 찾기 위하여 위임(delegation)모델을 사용한다. 각ClassLoader는 연관된 부모 클래스가 있다. 클래스나 자원(resource)를 찾으라는 요구를 받으면 ClassLoader 객체는 자신이 찾으려고 하기 이전에 부모 클래스 로더에 작업을 위임한다. VM에 내장된 클래스 로더 – “부트스트랩 클래스 로더(bootstrap class loader)” 는 부모 클래스로더를 가지고 있지 않으며, ClassLoader 객체의 부모로서 작업을 수행한다.
보통 자바 VM은 플랫폼 의존적인 방식으로 작동해, 로컬 파일 시스템으로부터 클래스들을 올리게 된다. 예를 들면 유닉스 시스템에서는 클래스패스 환경변수에 명시된 디렉토리로부터 클래스들을 읽어들인다.
그러나 어떤 클래스들은 파일로부터 기인하지 않는다. 네트워크와 같은 리소스로부터 발생하거나 애플리케이션에 의해 생성될 수도 있다. defileClass 메소드는 일련의 바이트 배열을 Class 클래스의 객체로 바꾸어 준다. 이렇게 새로 정의된 클래스의 객체는 Class.newInstance를 사용해서 생성할 수 있다.
클래스 로더에 의해 생성된 객체의 메소드와 생성자는 다른 클래스들을 참조할 수도 있다. 참조된 클래스(들)을 결정하기 위해서, 자바 VM은 그 클래스를 처음에 생성했던 클래스로더의 loadClass메소드를 실행한다.
예를 들어 애플리케이션은 서버로부터 클래스 파일들을 다운로드 받기 위해서 네트워크 클래스 로더를 생성할 수 있다. 아래 예제 코드를 보자.
ClassLoader loader = new NetworkClassLoader(host, port);
Object main = loader.loadClass("Main", true).newInstance();
네트워크 클래스 로더의 subclass는 네트워크로부터 클래스를 load하기 위해 findclass와 loadClassData 메소드를 정의해야 한다. 클래스를 생성하는 바이트코드를 다운로드받으면 클래스 로더는 클래스 객체를 생성하기 위해 defineClass 메소드를 사용해야 한다. 간단한 구현은 아래와 같다.
class NetworkClassLoader extends ClassLoader {
String host;
int port;
public Class findClass(String name) {
byte[] b = loadClassData(name);
return defineClass(name, b, 0, b.length);
}
private byte[] loadClassData(String name) {
// load the class data from the connection
. . .
}
}
정리하면,
각 클래스로더는 클래스를 찾아야 할 경우에 자신의 부모뻘 클래스로더에게 계속 작업을 위임한다. 결국 최상위 클래스로더로부터 클래스가 로딩되어 있는지 찾아 내려오고 없다면 자신이 생성하게 된다. 그러므로 모든 클래스는 한 번만 로딩되게 된다.
클래스의 객체 내부에서 다른 클래스를 찾는 경우, 그 클래스를 생성한 클래스로더가 그 클래스를 찾는다는 것...
참조 : http://crosscutter.info/tag/classloader