[JVM 완전정복 #2] 자바 프로그램의 첫 관문 - 클래스로더

2025. 11. 17. 21:34·자바

0. 들어가며

지난 글에서는 JVM의 전체 구성요소와 각 역할을 살펴보았습니다.
이번 글에서는 그중  클래스 로더(Class Loader)에 집중해 자바 프로그램 실행 시 클래스가 JVM 내부로 어떻게 올라가고 관리되는지 상세히 알아보겠습니다.

클래스 로더는 클래스(.class 파일)를 JVM 메모리에 불러오는 역할을 하는 프로그램 실행의 첫 관문이라고 할 수 있습니다.
JVM을 공부하다 보면 클래스 로더가 왜 필요한지 그리고 클래스 정보를 메모리에 미리 적재(pre-loading)하는 이유가 자연스럽게 궁금해지는데요.

이번 글에서는 클래스 로더가 수행하는 과정과 미리 적재하는 이유까지 상세히  다뤄보겠습니다.


1. 클래스 로더(Class Loader)란?

자바 프로그램이 실행되면 가장 먼저 클래스 로더가 동작합니다.

클래스 로더는 말 그대로 "클래스를 메모리에 올려주는 역할"을 합니다. 여기서 말하는 클래스는 우리가 작성한 .java 파일이 컴파일된 .class 파일을 의미합니다. 바이트코드로 변환된 클래스 파일은 연속된 바이트 스트림 형태로 존재하고 클래스 로더는 이를 JVM 내부로 가져와 실행 가능하게 만들어 줍니다.

클래스 로더는 .class 파일을 JVM 내부로 불러오고,링크·실행 준비까지 수행하는 매우 중요한 구성 요소입니다.

.class 파일은 JVM의 Class Loader Subsystem으로 전달되어 다음 과정을 거칩니다.

  1. 클래스 로딩: .class 파일을 읽어 메모리에 로드
  2. 바이트코드 검증: 코드가 안전한지 검증
  3. 메모리 할당: 프로그램 실행에 필요한 메모리를 할당

 

즉, 클래스 로더는 단순히 파일을 읽어오는 것뿐만 아니라 클래스 연결(Link)과 실행 준비( Initialization )까지 담당합니다.


1-1. 클래스 로더의 종류

클래스 로더는 하나가 아니라 기능과 범위에 따라 여러 종류로 나뉩니다.

  • 부트스트랩 클래스 로더(Bootstrap Class Loader)
    JVM이 처음 기동할 때, 자바에서 제공하는 기본 라이브러리(java.lang, java.util 등)를 로딩합니다. 운영 체제와 JVM 핵심이 필요로 하는 클래스들을 먼저 가져오는 역할을 합니다.
  • 플랫폼 클래스 로더(Platform Class Loader)
    이전에는 확장 클래스 로더(Extension Class Loader)라고 불렸지만 Java 9 이후부터는 /lib 디렉터리에 모듈화(Modularization) 되어 포함되는 방식으로 바뀌었습니다. JVM이 제공하는 추가 라이브러리나 모듈을 로딩하며 부트스트랩 클래스 로더가 처리하지 않은 클래스들을 담당합니다.
  • 애플리케이션 클래스 로더(Application Class Loader)
    우리가 직접 작성한   응용 프로그램 클래스와 외부 라이브러리 JAR 파일들을 로딩합니다. 일반적으로 클래스패스(classpath)에 지정된 경로에서 클래스를 찾아 메모리에 올리며, 애플리케이션 실행 시 가장 많이 사용하는 클래스 로더입니다.
클래스 로더역할
Bootstrap Class Loader JVM 기동 시 JDK 핵심 클래스(java.lang, java.util 등) 로딩
Platform Class Loader JDK 확장 라이브러리 및 모듈(/lib 경로) 로딩
Application Class Loader 개발자가 작성한 애플리케이션 클래스 로딩

1-2 클래스 로딩과 오류 영향  

클래스 로더는  클래스를 로드하고 실행 준비만 하는 것이 아닙니다.
클래스 로딩 과정은 다음 순서를 거칩니다.

로드(Load) → 링크(Link) → 초기화(Initialization) → 실행(Execution)

만약 이 과정에서 오류가 발생하면 해당 클래스의 로딩이 실패할 수 있으며 의존 관계가 있는 다른 클래스까지 영향을 미쳐 프로그램 전체 실행에 문제를 일으킬 수 있습니다.


때문에 클래스 로더 관련 오류는 운영 이슈와 직결되기도 하며 로딩 과정에서 발생할 수 있는 문제를 이해하는 것이 매우 중요합니다.


1-3. 동적 로딩과 런타임 처리

또한 클래스 로딩 시점은 프로그램에서 클래스가 필요해지는 순간마다 이루어집니다.

예를 들어 프로그램에 사용된 클래스가 100개라고 해도 JVM은 처음부터 100개를 모두 메모리에 올리지 않습니다.
필요한 클래스만 동적으로 로딩(Demand Loading) 하고, 실제 코드가 접근되는 순간에 링크와 실행까지 포함한 처리를 진행합니다.

이처럼 클래스 로더는 동적 로딩과 런타임 처리라는 독특한 특징을 가지고 있으며, 프로그램 실행 효율과 메모리 사용 최적화에 큰 영향을 줍니다.


2. 클래스 로더 내부 구조

클래스 로더는 바이트코드를 Byte Stream으로 가져오는 역할을 합니다.

여기서 Byte Stream 이란 .class 파일로 0과 1로 저장된 자바 바이트 코드가 연속되어 있기 때문에 이런형태의 데이터를 stream이라고 한다.

  • 클래스 로더는 부트스트랩 → 플랫폼 → 애플리케이션 순서로 계층 구조를 이루고
  • 상위 로더가 먼저 로딩을 시도하고 만약 찾지 못하면 하위 로더로 요청을 전달합니다.
  • 이 방식은 부모 위임 모델(Parent Delegation Model)이라 불리며 클래스 충돌과 중복 로딩 문제를 방지합니다. 

아래 그림을 보면서 더 자세히 알아봅시다.

이미지 출처 : https://javatutorial.net/jvm-explained/

3. 클래스 로더의 로딩·링킹·초기화 과정

자바에서 클래스 로더가 수행하는 과정은  .class 파일을 메모리에 올리는것 뿐만 아니라  JVM에서 클래스가 정상적으로 실행될 수 있도록 준비시키는 일련의 단계를 포함합니다. 이 과정은 크게 로드(Loading) → 링크(Linking) → 초기화(Initialization) 순으로 진행됩니다.

 


3-1. 로딩(Loading)

로딩 단계에서는 클래스 파일(.class)을 읽어 JVM이 이해할 수 있는 메모리 구조로 변환합니다.

1. 클래스 이름을 기반으로 클래스 파일 위치를 탐색합니다.
2. 클래스 바이트코드를 읽어 JVM Method Area에 로드 합니다.
3. 클래스에 대한 class 객체를 생성합니다.

이 단계에서 중요한 점은 아직 실행 준비가 완료된 상태가 아니라는 것입니다. 단순히 바이트코드와 클래스 메타데이터가 JVM에 올라간 상태라고 이해하면 됩니다.


3-2. 링크(Linking)

링킹 단계에서는 로드된 클래스가 JVM에서 실행될 수 있도록 외부 참조를 연결하고 검증하는 과정을 거칩니다. 링크는 다시 세 단계로 나뉩니다.

  1. 검증(Verification)
    • 바이트코드가 JVM 명세에 맞는지 확인합니다.
    • 잘못된 메서드 호출, 잘못된 타입 사용 등을 체크합니다.
    • 검증 실패 시 ClassFormatError, VerifyError 발생시킵니다.
  2. 준비(Preparation)
    • 클래스 변수(static field)를 JVM 메모리(Method Area)에 기본값으로 초기화합니다.
    • 예: int → 0, boolean → false, 객체 참조 → null
    • 여기서 실제 코드 초기화값은 아직 적용되지 않습니다.
  3. 해결(Resolution)
    • 클래스 내부의 참조(symbolic reference)를 실제 메모리 주소로 변환합니다.
    • 다른 클래스, 인터페이스, 상수풀(Constant Pool) 참조를 연결합니다.

링크 단계는 클래스의 안정성과 외부 의존성 처리에 집중하며, 이 과정에서 오류가 발생하면 NoClassDefFoundError와 같은 예외가 발생할 수 있습니다.


3-3. 초기화(Initialization)

초기화 단계에서는 클래스가 실제 사용 가능한 상태로 준비됩니다.

  • static 블록(static initializer) 실행
  • static 변수에 명시적으로 지정한 값 할당
  • 상속 관계에 있는 상위 클래스가 먼저 초기화

예를 들어 아래 코드가 있다면:

class A {
    static int x = 10;
    static { System.out.println("A 초기화"); }
}

class B extends A {
    static int y = 20;
    static { System.out.println("B 초기화"); }
}

 

B 클래스가 처음 사용될 때 JVM은 먼저 A 클래스 → B 클래스 순서로 초기화를 진행합니다.

요약하면 초기화 단계에서 클래스는 실제로 JVM에서 동작 가능한 상태가 되며 이 시점부터 클래스 메서드와 변수를 자유롭게 사용할 수 있습니다.


4. 왜 클래스를 미리 메모리에 올려둘까?

  • JVM이 클래스를 실행 도중에 필요할 때마다 디스크에서 계속 읽는다면 프로그램 실행 속도가 매우 느려질 것입니다.
    따라서 Class Loader는 프로그램 실행 전에 필요한 클래스 정보를 미리 메모리에 올려두고
    실행 중에는 이미 적재된 정보를 참조하여 빠르게 동작할 수 있도록 합니다.결과적으로 Class Loader는
    • 프로그램의 시작 속도를 높이고,
    • 중복 메모리 사용을 줄이며,
    • 클래스 재사용과 효율적인 참조를 가능하게 만드는 역할을 수행합니다.
  • 또한 클래스에 대한 정보(정의, 메서드, 상수 등)는 프로그램 전체에서 공유되어야 하는 데이터이기 때문에
    매번 새 객체가 생성될 때마다 같은 메서드 코드를 복사하는 것은 비효율적입니다.
    그래서 JVM은 이 정보를 공유 영역(Class Area) 에 한 번만 저장해두고모든 인스턴스가 이를 참조(Reference) 하는 방식으로 동작합니다.

5. 클래스 로더의 계층 구조

클래스 로더는 JVM에서 계층 구조로 존재하며 각 역할과 책임이 명확하게 나뉩니다. 이전에 간단히 소개했지만   더 상세히 살펴보겠습니다.

자바의 클래스 로더는 부모-자식 구조(Parent Delegation Model)를 따릅니다.
클래스를 로드할 때 항상 부모 클래스 로더에게 먼저 요청을 위임하고, 부모가 로드하지 못하면 자식이 처리하는 방식이죠.

클래스 로더설명
Bootstrap Class Loader JVM 기본 클래스 로더, java.lang., java.util. 등 JDK 핵심 클래스 로드
Platform Class Loader JDK 확장 라이브러리(jre/lib/ext/*.jar) 클래스 로드
Application Class Loader 애플리케이션 클래스 경로(classpath) 안의 클래스 로드

5-1.Bootstrap Class Loader

가장 기본이 되는 로더는 부트스트랩 클래스 로더(Bootstrap ClassLoader)입니다.
이름에서 알 수 있듯이 JVM 자체가 제공하는 핵심 클래스들을 메모리에 올리는 역할을 담당합니다.
예를 들어 java.lang.*나 java.util.* 같은 필수 라이브러리들이 여기에 속하죠.

이 로더는 JVM 내부에서 C++로 구현되어 있고 우리가 직접 접근할 수도 제어할 수도 없습니다.
JVM이 실행될 때 가장 먼저 실행되는 로더라고 생각하면 됩니다.


5-2. Platform Class Loader

다음 단계에 있는 것이 플랫폼 클래스 로더(Platform Class Loader)입니다. 이전에는 확장 클래스 로더(Extension Class Loader)라고 불렸지만, Java 9 이후부터는 /lib 디렉터리에 모듈화(Modularization) 되어 포함되는 방식으로 바뀌었습니다.

부트스트랩 클래스 로더가 기본적인 클래스들을 올렸다면, 플랫폼 클래스 로더는 JVM의 기능을 확장하는 라이브러리와 모듈들을 담당합니다. 필요할 때 이 로더가 클래스를 찾아 메모리에 로딩하며, 시스템 속성이나 모듈 경로를 통해 실제 로딩 위치를 확인할 수 있습니다. JVM이 제공하는 기능을 확장하고 싶다면 바로 이 단계에서 클래스를 로딩하게 되는 셈입니다.


5-3. Application ClassLoader

마지막으로 우리가 가장 자주 접하는 애플리케이션 클래스 로더(Application ClassLoader)가 있습니다.
이 로더는 개발자가 작성한 애플리케이션 클래스와 외부 라이브러리 JAR를 담당합니다.
일반적으로 클래스패스(classpath)에 지정된 경로에서 클래스를 찾아 메모리에 올리며 애플리케이션 실행 시 기본적으로 사용되는 로더이기도 합니다.

흥미로운 점은,JVM이 로딩할 때 항상 상위 로더부터 요청을 보내는 Parent Delegation Model을 따른다는 것입니다. 애플리케이션 클래스 로더가 어떤 클래스를 로딩하려고 하면 먼저 확장 클래스 로더 그 다음 부트스트랩 클래스 로더에게 먼저 물어보고 이미 로딩된 클래스가 있으면 그걸 재사용합니다. 이렇게 상위 로더가 책임을 먼저 가지게 하면 클래스 중복 문제나 보안 이슈를 방지할 수 있습니다.


이 계층 구조 덕분에 JVM은 동적으로 클래스를 로딩하면서도 안정성과 보안을 확보할 수 있습니다. 필요하다면 런타임에 네트워크나 파일 시스템에서 클래스를 받아와 로딩할 수도 있고, 인터페이스만 맞으면 아직 구현체가 없어도 프로그램이 실행될 수 있는 유연성을 제공합니다. 즉, 클래스 로더의 구조와 동작 방식 덕분에 자바는 확장성, 보안성, 유연성을 동시에 갖출 수 있는 언어가 된 것입니다.

 

마치며

 

이번에 클래스 로더를 정리하면서 런타임에 클래스가 로드 → 링크 → 초기화 → 실행되는 과정을 하나하나 따라가보니 왜 가끔 단순한 클래스 하나 때문에 프로그램 전체가 꼬이는지 이해할 수 있었습니다.
이런 과정을 알게 되니 JVM 내부에서 클래스가 어떻게 살아 움직이는지 직접 보는 느낌이 들어 재밌는 시간이었습니다.

다음에는 JVM의 runtime data area에 대해 다루어 보겠습니다.

다음 글에서 또 만나요~

 

저작자표시 비영리 (새창열림)

'자바' 카테고리의 다른 글

[JVM 완전정복 #4] Garbage Collector 이해하기  (0) 2025.11.17
[JVM 완전정복 #3] Runtime Data Area 완전분석: 메모리 구조와 각 영역 역할  (0) 2025.11.17
JIT 컴파일러와 일반 컴파일러의 차이를 알아보자  (0) 2025.11.14
Java Class 하위에 변수를 몇개까지 선언할 수 있을까?  (0) 2025.11.11
[JVM 완전정복 #1] JVM 구성요소 총정리: 가상 머신이 자바 코드를 실행하는 비밀  (0) 2025.11.11
'자바' 카테고리의 다른 글
  • [JVM 완전정복 #4] Garbage Collector 이해하기
  • [JVM 완전정복 #3] Runtime Data Area 완전분석: 메모리 구조와 각 영역 역할
  • JIT 컴파일러와 일반 컴파일러의 차이를 알아보자
  • Java Class 하위에 변수를 몇개까지 선언할 수 있을까?
깊은바다속꼬북이
깊은바다속꼬북이
  • 깊은바다속꼬북이
    CodeBlossom
    깊은바다속꼬북이
  • 전체
    오늘
    어제
    • 분류 전체보기 (53) N
      • 라이징 캠프 (4)
      • 객채지향 개발론 (3)
      • 스프링 (10) N
      • 네트워크 (2)
      • 자바 (16)
      • 자료구조 (3)
      • 운영체제 (0)
      • 데이터베이스 (4)
      • 디자인패턴 (7)
      • JSP (1)
      • 개발 알쓸신잡 (2)
      • 일반 교양 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    객체지향
    JUnnit5
    개발 철학
    java
    MySQL 옵티마이저
    junnit5프레임워크
    전략 패턴(Strategy Pattern)
    스프링
    한국어 검색
    디자인패턴
    개발자 철학
    템플릿 메서드 패턴(Template Method Pattern)
    트랜잭션 전파레벨
    디자인 패턴
    mockito라이브러리
    spring
    java data area
    MySQL 파서
    자료구조
    어댑터 패턴(Adapter Pattern)
    jit-compiler
    jvm 클래스 로더
    싱글턴 패턴(Singleton Pattern)
    GC
    자바 Socket 클래스
    개발 교훈
    프로그램밍 언어
    JVM
    java 버전별 특징
    백엔드
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
깊은바다속꼬북이
[JVM 완전정복 #2] 자바 프로그램의 첫 관문 - 클래스로더
상단으로

티스토리툴바