WAS/WebLogic

[개요] 클래스 로더(Class Loader) 이해

투칼론 2015. 5. 13. 23:10
반응형


1. 자바 언어에서 클래스 로더(Class Loader) 정의 및 특징 

클래스 로더(Class Loader)는 컴파일 시점(Compile Time)이 아닌 실행 시점(Run Time)에 클래스(Class)를 로딩할 수 있게 해주는 기술이다. 예를 들어, ClassA = new HelloWorld(); 라는 코드를 최초로 실행할 때, 자바 가상 머신(JVM)은 HelloWorld라는 클래스를 클래스 로더를 통해서 메모리에 로드하게 된다. 클래스는 로더는 클래스의 바이트 코드(Bytecode)를 파일 시스템 상의 클래스나, JAR와 같은 아카이브(Archive) 형태로 동적으로 로딩할 수 있도록 지원해준다.


이 클래스 로더는 기술적으로 아래와 같은 특징을 가지고 있다.


계층적(Hierarchical)

     : 클래스 로더는 계층적으로 생성이 가능하다. 상위(Parent) 클래스 로더에서 하위(Child) 클래스 로더를 갖는것과 같이 클래스 로더 간의 계층형 구조를 갖게 되며, 최상위 클래스 로더는 부트스트랩(Bootstrap) 클래스 로더가 위치하게 된다. 


위임형 로드 요청(Delegate Load Request)

     : 상위 클래스 로더가 로딩한 클래스가 우선권을 가진다. 예를 들어, 클래스 로더가 상위로 부터 각각 CL1  - CL2 - CL3 라고 가정하면, CL3가 특정 클래스를 로딩 시에 해당 클래스 로딩을 CL2로 요청하고, CL2는 다시 CL1으로 로딩을 요청한다. 


가시적인 규약(Visibility constraint)

     : 상위 클래스 로더를 먼저 참조하고, 클래스 로더는 일종의 범위 룰(Scope Rule)을 제공하는데, 하위 클래스 로더는 상위 클래스 로더의 클래스를 위임형 로드 요청(Delegation load request)을 이용하여 찾을 수 있지만, 반대로 상위 클래스로더는 하위 클래스 로더가 로딩한 클래스를 사용할 수 없다. 

또한, 상위 클래스 로더가 같은 하위 클래스 로더는 서로 로딩한 클래스를 사용할 수 없게 되어 있다.


클래스는 언로드 할 수 없음(Cannot unload classes)

     : 클래스 로더에 의해서 로딩된 클래스들은 언로드(Unload)될 수 없다. 클래스 로더에는 클래스 언로딩(Unloading) 기능이 없고, 이를 구현하기 위해서는 클래스 로더 자체를 삭제하고, 새로운 클래스 로더를 생성하여 다시 클래스 로더를 로딩하면, 재로드(Reload)되는 것처럼 작동하는 것이 된다.


2. 클래스 로더(Class Loader) 구조 



클래스 로더는 상위로 부터 순서대로 부트스트랩(Bootstrap), 확장(Extensions), 시스템(System) 클래스로더가 순서대로 올라간다. 즉, 동일한 클래스가 여러 곳에 존재할 때 로딩되는 우선순위는 Bootstrap>Extensions>System Class Loader가 된다.

- 부트스트랩(Bootstrap) Class Loader

     : 자바 가상 머신이 실행될때 가장 먼저 실행되는 클래스 로더로, JAVA 실행에 필요한 기본적인 클래스들($JAVA_HOME/jre/lib/rt.jar)을 로딩한다. 다른 클래스 로더와 달리 자바가 아니라 네이티브 코드로 구현되어 있다.


- 확장(Extensions) Class Loader

    : 추가로 로딩되는 클래스들로 $JAVA_HOME/lib/ext/*.jar에 있는 JAVA 확장 클래스들이 로딩된다. 이 클래스들은 별도로 클래스패스(Classpath)에 설정되어 있지 않아도 로딩된다. 다양한 보안 확장 기능 등을 여기에서 로드하게 된다.


- 시스템(System) Class Loader

   : CLASSPATH에 정의되거나 JVM 옵션에서 -cp, -classpath에 지정된 클래스들이 로딩된다. 시스템 클래스 로더는 애플리케이션의 클래스들을 로드한다고 할 수 있다. 즉, 사용자가 지정한 $CLASSPATH 내의 클래스들을 로드한다. 


- 사용자 정의(User-Defined) Class Loader

  : 애플리케이션 사용자가 직접 코드 상에서 생성해서 사용하는 클래스 로더이다.


추가적으로 설명하면, 클래스 로더가 클래스 로드를 요청받으면, 상위 클래스 로더, 자기 클래스 로더 순서로 해당 클래스가 이미 로딩되어 있는지 확인한다. 즉, 이전에 로드된 클래스인지 상위 클래스 로더를 거슬러 올라가며 확인한다. 부트스트랩 클래스 로더까지 확인해도 없으면 요청받은 클래스 로더가 파일 시스템(CLASSPATH 등 기준)에서 해당 클래스를 찾는다.


3. 웹로직(WebLogic) 클래스 로더 이해


위에서 설명한 클래스 로더에서 웹로직 클래스 로더는 사용자 정의(User-defined) 클래스 로더라고 할 수 있다. 바로 위 부모 클래스 로더는 시스템 클래스 로더이다.

웹로직에서는 EJB JAR, WAR, EAR을 로딩하는 세 종류의 클래스 로더가 있다.


EJB-JAR 클래스 로더

: EJB를 JAR 형식으로 배포하면, JAR 1개 당 EJB-JAR 클래스 로더가 생성된다. 즉, 서로 JAR 간에는 클래스를 참조할 수 없고, System 클래스 로더 이상의 상위 클래스 로더의 클래스들(CLASSPATH 설정된 클래스)을 참조할 수 있다. 아니면 필요한 클래스(예, 다른 EJB의 Remote Interface, Home Interface 등)들을 동일한 JAR에 패키징해야 한다. 


WAR 클래스 로더

: JSP나 서블릿(Servlet)을 로딩하는 클래스 로더이다. 이 WAR 클래스 로더는 위에서 설명한 클래스 로더의 특징을 가지고 있지만, 주의할 점은 클래스 로딩 우선 순위를 일반적인 상위 클래스 로더보다 WEB-INF/classes와 WEB-INF/lib 디렉토리를 우선 로딩할 수 있도록 할 수 있다는 것이다. 설정 방법은 웹로직 관리 웹콘솔에서 PreferWebInfClasses를 true로 설정하면 된다.


EAR 클래스 로더

: EAR을 로딩하는 클래스 로더로서, 내부적으로 EJB-JAR 클래스 로더와 WAR 클래스 로더가 부모-자식 관계로 생성된다는 것이 특징이다. 즉 서블릿/JSP에서 EJB를 참조하여 호출 가능하다는 의미이다. 이유는 서블릿/JSP가 로딩된 WAR 클래스 로더의 부모 클래스 로더가 EJB를 로딩하는 EJB-JAR 클래스 로더이기 때문이다.

아래 그림의 클래스 로더 구조에서는 WebApp1은 EJB1과 EJB2를 참조하여 호출할 수 있고, WebApp2와 WebApp3는 EJB3를 참조하여 호출할 수 있다. 그러나 EJB1/EJB2와 EJB3를 로딩하는 클래스 로더가 부모-자식 관계가 아니기 때문에 서로 참조를 하지 못한다.


4. 웹로직(WebLogic)에서 패키징(Packaging)


패키징을 하는 데 있어 서블릿/JSP에서 EJB를 호출하는데 있어, EJB의 클라이언트 클래스(EJB Remote Interface, EJB Home Interface 등)와 EJB에서 공통으로 사용하는 공통 클래스를 어떻게 패키징할 것인가가 큰 이슈가 될 것 이다.


1) WEB-INF/lib 또는 WEB-INF/classes 폴더에 EJB 클라이언트 클래스와 공통 클래스를 배포

2) EJB-JAR 형태의 JAR로 패키징

3) CLASSPATH로 설정

4) EJB-JAR 형태로 EAR에 배포

5) EAR의 APP-INF/lib 또는 APP-INF/classes에 공통 클래스 배포 


[관련 다른글]

http://blueyikim.tistory.com/1181