이제 본격적으로 JVM이라는 Java의 아주 핵심이 되는 친구에 대해서 하나씩 알아보자. 물론 깊게 들어갈거다.
일단 아래의 그림을 보자.
여기 보면 이제 말 그대로 자바는 어떻게 실행되는지에 대한 과정이 차례대로 나와있다. 물론! 이 그림대로만 설명을 해도 되겠지만 여기에 존재하는 각각의 기능들이 다 중요한 기능이라서 챕터를 나눠서 볼려고 한다!
이번 시간에는 Class Loader에 대해서 알아보자!
위에 과정에서도 설명하였지만 간단하게 설명하면은 컴파일러에 의하여서 바이트 코드로 바뀐 것을 JVM의 Runtime Data Area영역으로 적재시키는 역할을 해준다. 그리고 다음과 같은 역할을 한다고 한다!
클래스 로더는 “. class” 파일에서 해당 바이너리 데이터를 생성하여 메소드 영역에 저장합니다.
런타임 상수 풀의 기호 참조가 실제로 필요한 유형의 유효한 클래스를 가리키는지 확인하는 것을 의미합니다. 기호 참조의 확인은 참조된 클래스의 로드를 트리거합니다. JVM 사양에 따르면 이 해결 프로세스는 느리게 수행될 수 있으므로 클래스가 사용될 때까지 연기됩니다.
Verification, preparation를 실행시킵니다.
- Verification: class 파일 의 정확성을 보장합니다. 즉, 이 파일이 올바른 형식으로 되어 있고 유효한 컴파일러에 의해 생성되었는지 여부를 확인합니다. 확인에 실패하면 런타임 예외 java.lang.VerifyError 가 발생 합니다. 이 활동은 구성 요소 ByteCodeVerifier에 의해 수행됩니다. 이 활동이 완료되면 클래스 파일을 컴파일할 준비가 된 것입니다.
- Preparation : JVM은 클래스 정적 변수에 대한 메모리를 할당하고 메모리를 기본값으로 초기화합니다.
이 단계에서 모든 정적 변수는 코드 및 정적 블록(있는 경우)에 정의된 값으로 할당됩니다. 클래스에서는 위에서 아래로, 클래스 계층에서는 부모에서 자식으로 실행됩니다.
위와 같은 역할을 진행 하는데 있어서 단일의 Class Loader로만 진행을 할까? 그건 또 아니라고 한다.
BootStrap Class Loader : 모든 JVM 구현에는 신뢰할 수 있는 클래스를 로드할 수 있는 부트스트랩 클래스 로더가 있어야 합니다. " JAVA_HOME/jre/lib" 디렉토리 에 있는 핵심 Java API 클래스를 로드합니다 . 이 경로는 일반적으로 부트스트랩 경로로 알려져 있습니다. C, C++와 같은 네이티브 언어로 구현됩니다.
Extension Class Loader : 부트스트랩 클래스 로더의 자식입니다. 확장 디렉토리 " JAVA_HOME/jre/lib/ext" (확장 경로) 또는 java.ext.dirs 시스템 특성에 의해 지정된 다른 디렉토리에 있는 클래스를 로드합니다. 이것은 sun.misc.Launcher$ExtClassLoader 클래스에 의해 자바에서 구현됩니다.
System/Application Class Loader : 확장 클래스 로더의 자식입니다. 애플리케이션 클래스 경로에서 클래스를 로드하는 역할을 합니다. 내부적으로 java.class.path에 매핑된 환경 변수를 사용합니다. 또한 sun.misc.Launcher$AppClassLoader 클래스에 의해 Java로 구현됩니다.
이렇게 3가지가 존재한다고 하는데 작동을 할 때 Delegation-Hierarchy
의 원칙에 따라서 클래스를 로드한다고 한다. (한국말로 위임-계층이라고 생각하니 이해가 쉬웠다.)
BootStrap부터 시작하여 없으면 Extension 없으면 System/Application 순서대로 가게 된다.
여기서 위 클래스 로더들에서 공통적으로 말하는 것들이 클래스를 로드한다는 거다! 그러면 만약에 이상한 클래스를 불러서 컴파일을 시킨다? 하면 java.lang.ClassNotFoundException
이 발생하는거니까 이런 문제가 생기면 컴파일 문제라는 것을 잘 알고 가자!