클래스 로더는 JVM내로 클래스를 동적으로 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈이다.
클래스 로더는 여러 클래스 로더끼리 부모-자식 관계를 이룬 계층적인 구조이다. 각 클래스 로더를 정리하면 다음과 같다.
부트스트랩 클래스 로더(Bootstrap Class Loader)
익스텐션 클래스 로더(Extension Class Loader)
시스템 클래스 로더(System Class Loader)
사용자 정의 클래스 로더(User-Defined Class Loader)
위임모델이란 처음 바이트 코드를 넘겨받은 클래스 로더가 필요한 클래스를 로드할 때 혹은 실행 엔진에서 명령어 단위로 바이트 코드를 실행하다가 처음으로 참조하는 클래스에 대해 클래스 로더에게 로드를 요청할 때 로드를 요청받은 클래스 로더는 다음과 같은 순서대로 요청받은 클래스가 있는지 확인한다.
1. 클래스 로더 캐시
이전에 로드된 클래스인지 클래스 로더 캐시를 확인한다.
2. 상위 클래스 로더
찾으려는 클래스가 클래스 로더 캐시에 없으면 상위 클래스 로더를 하나씩 거슬로 올라가며 확인한다.
이 때, 올라가는 도중에 클래스를 발견하더라도 부트스트랩 클래스 로더까지 확인한 후 해당 클래스가 존재하면 부트스트랩 클래스 로더에 있는 클래스를 로드한다.
3. 파일 시스템
부트스트랩 클래스 로더에도 해당 클래스가 없으면 로드를 요청받은 클래스 로더가 파일 시스템에서 해당 클래스를 찾는다.
파일 시스템에서도 클래스를 찾지 못하면 ClassNotFoundException가 발생한다.
계층 구조로 되어있는 클래스 로더에서 하위 클래스 로더는 상위 클래스 로더가 로드한 클래스를 볼 수 있지만, 상위 클래스 로더는 하위 클래스 로더가 로드한 클래스를 볼 수 없는 것을 의미한다.
가시 범위 원칙이 없다면 계층 구조가 없는 클래스 로더가 되고, 격리 레벨 없이 모든 것을 읽어와야 한다.
클래스를 로드하는 것은 가능하지만 반대로 언로드하는 것은 불가능하다.
각 클래스 로더들이 가지고 있으며, 로드된 클래스를 보관하는 공간이다.
클래스를 로드할 때 위임 모델을 통해 상위 클래스 로더들을 확인하는데 그 때 확인하는 공간이 이곳이다.
클래스들은 FQCN(Fully Qualified Class Name)을 기준을 보관되는데, FQCN이란 패키지명까지 포함되어있는 식별자를 뜻한다.
각각의 클래스 로더가 각자 이름 공간을 가지고 있기 때문에 FQCN이 같은 클래스라도 다른 클래스 로더가 로드한 클래스라면 다른 클래스로 간주한다.
이 특성을 이용하면 언로드를 대신해서 로드한 클래스 로더를 제거하면 마치 언로드한 것과 같은 효과를 줄 수 있다.
1. 로드: 클래스 파일을 가져와서 JVM의 메모리에 로드한다.
2. 검증: 클래스 로드 전 과정 중에서 가장 복잡하고 시간이 많이 걸리는 과정으로, 읽어들인 클래스가 자바 언어 명세(Java Language Specification) 및 JVM 명세에 명시된 대로 구성되어 있는지 검사한다.
3. 준비: 클래스가 필요로 하는 메모리를 할당한다. 필요한 메모리란 클래스에서 정의된 필드, 메소드, 인터페이스들을 나타내는 데이터 구조 등을 말한다.
4. 분석: 클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경한다.
5. 초기화: 클래스 변수들을 적절한 값으로 초기화한다. (static 필드들을 설정한 값으로 초기화 등)
JVM이 OS로부터 할당받는 메모리 영역이다. 각 스레드마다 PC 레지스터, JVM 스택, 네이티브 메소드 스택이 하나씩 생성되고 힙과 메소드 영역은 모든 스레드가 공유한다.
스레드가 시작될 때 생성되며 각 스레드마다 하나씩 존재한다. 스레드가 어떤 부분을 어떤 명령으로 실행해야할 지에 대한 기록을 하는 부분으로, 현재 수행 중인 JVM 명령의 주소를 갖는다.
[참고]