|
|
|
|
자바와 닷넷에서 원하는 클래스를 찾아 가는 방식에 대해 살펴보기로 한다.
Java : 대체로 클래스패스에 의존한다. 실행 시 클래스패스가 정의되지 않은 경우, 현 디렉토리만을 자신의 실행 패스로 간주한다. 클래스패스는 환경변수에 정의되어 있어 있는 경우가 일반적이며, 어플리케이션에 따라 필요한 클래스를 패스를 추가하여 구성하기도 한다. WAS를 사용할 경우 탐색의 효율성을 높이기 위해 환경변수의 클래스패스를 무시하고 WAS내에서 재정의하여 사용하는 경우가 일반적이며, 클래스패스에 잡히지 않더라도 WAS내의 약속된 디렉토리가 자동적으로 클래스패스에 추가되기도 한다. WAS를 사용할 경우, 어플리케이션의 종류에 따라서 사용되는 classloader가 달라지며 클래스 탐색은 좀 더 복잡한 양상을 띤다.
자바의 classloader는 계층화되어 정의되어 있고, 각 계층별 classloader는 자신이 탐색하는 영역(디렉토리)이 정의되어 있고 하위 계층의 classloader가 탐색에 실패하면 상위 계층의 classloader가 자신의 영역을 탐색하게 된다. Classloader의 계층별 종류에 따른 우선 순위 및 명칭은 JEE 스펙에 명시되어 있으나, 특정 WAS내에서 특정 classloader가 관장하는 디렉토리가 WAS마다 상이하며 (비록 classloader는 JEE 스펙에 명시되어 같은 이름으로 불릴지라도..), 어플리케이션의 종류에 따라 classloader를 계층화하는 방법 또한 WAS마다 조금씩 상이하기 때문에 클래스 로딩 현상이 자신이 기대한 바와 다르다면 해당 WAS의 classloading 방식을 참조하는 것이 현명하다.
자바는 jar를 통해 패키지에 버전 정보를 기술할 수 있으나 닷넷 만큼 그 중요성이 크지 않고 그 용도가 다르며 광범위하게 사용되지 않는 경향이 있다. Jar의 버전 정보가 다르다고 해서 로딩되지 않은 것은 아니다. 클래스에 대한 시그너쳐만 같다면 로딩에 아무 문제가 없어 실행시 버전에 따른 차이로 인해 오류가 발생할 수도 있다. 이의 연장선상에서 WAS 사용시 흔히 겪는 문제중 하나가 WAS 별로 정의되어 있는 classloader별 탐색 디렉토리에 관한 것이다. 해당 WAS의 classlaoder별로 지정된 디렉토리 여러 곳에 실질 버전이 다른, 같은 이름의 jar 패키지가 존재한다면, 어플리케이션에 따라 관여하는 classloader가 다르며, 관여하는 순서에 따라 로딩되는 클래스의 버전이 달라지게 되어 디버깅에 무척 애를 먹을 수 있다. 또한 상위 classlaoder는 하위 classlaoder가 로드한 클래스를 볼 수 없으며(역으로는 가능하다), 같은 클래스가 서로 다른 classloader에 의해 로드된다면, JVM은 서로 다른 클래스로 간주하는 등 클래스로딩에 관해 알아야 할 것들이 있다. 또한 classloader의 lifecycle이 다르기 때문에 어느 classlaoder에서 클래스가 로딩되는 가도 중요한 변수가 된다. 자바의 경우 classloader가 내려가면 이 classlaoder가 로딩한 모든 클래스가 unload된다. (참고로, jsp와 ejb를 포함한 .ear를 썬 WAS에 디플로이하면, bootstrap classloader -> ext classloader -> system classloader -> common classloader -> share classloader -> ejb classloader -> web classloader -> jsp classloader 등이 관여하게 된다.)
.net : 닷넷의 경우, 자바와 달리 어셈블리의 버전 정보가 매우 중요한 탐색 기준이 된다. 어셈블리에 명시된 대상 어셈블리의 버전과 일치하는 어셈블리가 일차 목표이다. 하지만, machine.config나 app.config 등을 통해 버전 바인딩을 설정할 수 있기 때문에 이러한 configuration 파일을 조사한 후 CLR은 찾고자 하는 어셈블리의 정확한 버전을 결정하게 된다. 버전이 결정되면 CLR은 필요로 하는 어셈블리가 이미 메모리에 로드되었는지를 검사하여 만약 로드되었다면 이를 사용하고 그렇지 않다면 어셈블리를 찾기 위한 탐색을 시작한다. CLR이 가장 먼저 조사할 곳은 GAC이다. GAC에서 발견되지 않는다면 어플리케이션의 configuration 파일에 기재되어 있는 codebase 항목을 조사하게 된다. 만약, configuration 파일에 codebase가 정의되어 있고 codebase가 지정한 디렉토리에 해당 어셈블리가 없을 경우 CLR의 탐색은 실패를 나타내며 종료된다. 즉, 어플리케이션이 의도한 곳에 어셈블리가 없기 때문에 더 이상의 탐색 없이 실패로 종료된다. Codebase 항목이 지정되어 있지 않다면, CLR은 어플리케이션 기반의 probing 과정을 진행하게 된다. 즉, 어플리케이션이 위치한 곳을 중심으로 어셈블리를 찾기 위한 작업이 진행된다. 이러한 과정이 실패한 후에도 CLR은 어셈블리의 이름이나 culture 등등을 근거로 좀 검색 과정을 더 진행하게 된다.
|
|
|
|
|
http://acroama.isblog.net/trackback_post_2.aspx