Class Loader

.class 파일(바이트코드)을 JVM 메모리에 동적으로 로드·링크·초기화하는 JVM의 서브시스템입니다.

동작 3단계

.class 파일 → [ Loading ] → [ Linking ] → [ Initialization ] → 사용 가능

1단계: Loading (로딩)

.class 파일을 읽어 바이너리 데이터를 Method Area에 저장하고, Heap에 해당 클래스의 Class<?> 객체를 생성합니다.

로딩은 세 가지 계층의 클래스 로더가 담당합니다.

클래스 로더로딩 대상예시
BootstrapJVM 핵심 클래스java.lang.*, java.util.*
Extension (Platform)확장 라이브러리javax.*, jdk.*
Application (System)사용자 애플리케이션classpath에 있는 클래스

2단계: Linking (링크)

하위 단계설명
Verify바이트코드가 JVM 스펙에 맞는지 검증 (보안 핵심)
Preparestatic 변수에 메모리 할당 후 기본값(0, null 등) 설정
Resolve심볼릭 참조를 실제 메모리 주소(직접 참조)로 변환

3단계: Initialization (초기화)

static 변수에 코드에 명시된 값을 대입하고 static { } 블록을 실행합니다.

class Example {
    static int count = 10;   // Prepare: 0 → Initialization: 10
    static {
        System.out.println("초기화 완료");
    }
}

위임 모델 (Delegation Model)

클래스 로더의 핵심 원칙은 부모 위임 모델(Parent Delegation Model) 입니다.

요청: "String 클래스 로드해줘"

Application ClassLoader
  │  "나는 모른다, 부모에게 위임"
  ▼
Extension ClassLoader
  │  "나도 모른다, 부모에게 위임"
  ▼
Bootstrap ClassLoader
  └─ "내가 로드할게!" ← java.lang.String 로드 완료

동작 순서는 다음과 같습니다. 클래스 로드 요청이 들어오면 먼저 부모 로더에게 위임하고, 부모가 찾지 못하면 자기 자신이 탐색합니다. 최상위(Bootstrap)까지 올라가도 못 찾으면 ClassNotFoundException이 발생합니다.

왜 부모 위임을 사용하는가?

// 악의적인 사용자가 직접 만든 클래스
package java.lang;
public class String {
    // 악성 코드 ...
}

부모 위임이 없다면 이 가짜 String이 로드될 수 있습니다. 부모 위임 모델 덕분에 java.lang.String은 항상 Bootstrap 로더가 먼저 로드하므로, 핵심 클래스의 위변조를 방지할 수 있습니다.

부모 위임을 깨는 사례

사례이유
JDBC (SPI)Bootstrap이 로드한 인터페이스가 Application 레벨 드라이버 구현체를 찾아야 함 → Thread.currentThread().getContextClassLoader() 사용
톰캣 (WAS)여러 웹앱이 동일 클래스를 서로 다른 버전으로 사용 → 앱별 독립 클래스 로더
OSGi모듈 간 클래스 격리·공유를 세밀하게 제어 → 네트워크형 위임

핵심 정리

클래스 로더는 로딩 → 링크 → 초기화 세 단계로 클래스를 메모리에 적재하며, 부모 위임 모델을 통해 중복 로딩을 방지하고 핵심 클래스의 무결성을 보장합니다. 이 구조 덕분에 JVM은 런타임에 필요한 클래스만 동적으로 불러오는 지연 로딩(Lazy Loading) 이 가능합니다.

CSLOG에서 보기