📚FOS Study
홈카테고리
홈카테고리

카테고리

  • AI 페이지로 이동
    • RAG 페이지로 이동
    • agents 페이지로 이동
    • BMAD Method — AI 에이전트로 애자일 개발하는 방법론
    • Claude Code의 Skill 시스템 - 개발자를 위한 AI 자동화의 새로운 차원
    • Claude Code 멀티 에이전트 — Teams
    • 멀티모달 LLM (Multimodal Large Language Model)
  • architecture 페이지로 이동
    • 캐시 설계 전략 총정리
    • 디자인 패턴
    • 분산 트랜잭션
  • css 페이지로 이동
    • FlexBox 페이지로 이동
  • database 페이지로 이동
    • mysql 페이지로 이동
    • opensearch 페이지로 이동
    • redis 페이지로 이동
    • 김영한의-실전-데이터베이스-설계 페이지로 이동
    • 커넥션 풀 크기는 얼마나 조정해야할까?
    • 인덱스 - DB 성능 최적화의 핵심
    • 역정규화 (Denormalization)
    • 데이터 베이스 정규화
  • devops 페이지로 이동
    • docker 페이지로 이동
    • k8s 페이지로 이동
    • k8s-in-action 페이지로 이동
    • monitoring 페이지로 이동
  • go 페이지로 이동
    • Go 언어 기본 학습
  • http 페이지로 이동
    • HTTP Connection Pool
  • interview 페이지로 이동
    • 210812 페이지로 이동
    • 뱅크샐러드 AI Native Server Engineer
    • CJ 올리브영 지원 문항
    • CJ 올리브영 커머스플랫폼유닛 Back-End 개발 지원 자료
    • 마이리얼트립 - Platform Solutions실 회원주문개발 Product Engineer
    • NHN 서비스개발센터 AI서비스개발팀
    • nhn gameenvil console backend 직무 인터뷰 준비
    • 면접을 대비해봅시다
    • Tossplace Node.js Developer
    • 토스플레이스 Node.js 백엔드 컬처핏
  • java 페이지로 이동
    • jdbc 페이지로 이동
    • opentelemetry 페이지로 이동
    • spring 페이지로 이동
    • spring-batch 페이지로 이동
    • 더_자바_코드를_조작하는_다양한_방법 페이지로 이동
    • Java의 로깅 환경
    • MDC (Mapped Diagnostic Context)
    • OpenTelemetry 란 무엇인가?
    • Java StampedLock — 읽기 폭주에도 쓰기가 밀리지 않는 락
    • Virtual Thread와 Project Loom
  • javascript 페이지로 이동
    • Data_Structures_and_Algorithms 페이지로 이동
    • Heap 페이지로 이동
    • typescript 페이지로 이동
    • AbortController
    • Async Iterator와 제너레이터
    • CommonJS와 ECMAScript Modules
    • 제너레이터(Generator)
    • Http Client
    • Node.js
    • npm vs pnpm 선택기준은 무엇인가요?
    • `setImmediate()`
  • kafka 페이지로 이동
    • Kafka 기본
    • Kafka를 사용하여 **데이터 정합성**은 어떻게 유지해야 할까?
    • 메시지 전송 신뢰성
  • linux 페이지로 이동
    • fsync — 리눅스 파일 동기화 시스템 콜
    • tmux — Terminal Multiplexer
  • network 페이지로 이동
    • L2(스위치)와 L3(라우터)의 역할 차이
    • L4와 VIP(Virtual IP Address)
    • IP Subnet
  • react 페이지로 이동
    • JSX 페이지로 이동
    • VirtualDOM 페이지로 이동
    • v16 페이지로 이동
  • task 페이지로 이동
    • ai-service-team 페이지로 이동
    • nsc-slot 페이지로 이동
    • the-future-company 페이지로 이동
📚FOS Study

개발 학습 기록을 정리하는 블로그입니다.

바로가기

  • 홈
  • 카테고리

소셜

  • GitHub
  • Source Repository

© 2025 FOS Study. Built with Next.js & Tailwind CSS

목록으로 돌아가기
☕java/ 더_자바_코드를_조작하는_다양한_방법

클래스 로더 시스템

약 3분
2026년 1월 30일
2026년 3월 24일 수정
GitHub에서 보기

클래스 로더 시스템

JVM이 .class 파일을 읽어서 메모리에 올리는 과정을 담당한다.


클래스 로더 계층 구조

Bootstrap ClassLoader   ← JVM 내장 (C/C++), java.lang.* 등 핵심 라이브러리
    └─ Platform ClassLoader   ← Java 9+, 확장 모듈 (java.sql.*, javax.*)
         └─ Application ClassLoader   ← 애플리케이션 클래스패스의 클래스들
  • Bootstrap: JVM 구현에 따라 다름. Java 코드에서 참조 불가 (null 반환)
  • Platform: Java 8 이전의 Extension ClassLoader
  • Application: 개발자가 만든 클래스 대부분이 여기서 로딩됨

부모 위임 모델 (Parent Delegation)

클래스 로딩 요청이 오면 자신이 직접 찾기 전에 부모에게 먼저 위임한다.

Application ClassLoader가 java.lang.String 요청
    → Platform ClassLoader에 위임
    → Bootstrap ClassLoader에 위임
    → Bootstrap이 rt.jar에서 찾아서 로딩 성공
    → Application까지 내려오지 않음

덕분에 java.lang.String을 직접 만들어도 실제로 로딩되지 않아서 핵심 클래스를 변조할 수 없다.


클래스 로딩 3단계

1. 로딩 (Loading)

.class 파일을 읽어서 바이너리 데이터를 만들고 메소드 영역에 저장한다. 저장 내용: FQCN(패키지 포함 클래스명), 클래스/인터페이스/Enum 구분, 메소드·변수 정보 로딩 완료 후 해당 클래스 타입의 Class 객체를 힙 영역에 생성한다.

2. 링크 (Linking)

세 단계로 구성된다.

  • Verify: .class 파일 형식이 JVM 스펙에 맞는지 검증
  • Prepare: static 변수에 필요한 메모리 할당 + 기본값 초기화 (int → 0, 참조 → null)
  • Resolve: 심볼릭 레퍼런스를 메소드 영역의 실제 레퍼런스로 교체 (optional)

3. 초기화 (Initialization)

static 변수를 코드에서 지정한 값으로 초기화하고, static 블록을 실행한다.

static int count = 10;  // Prepare에서 0, 초기화에서 10으로 설정
static {
    System.out.println("초기화 실행");  // 여기서 실행
}

ClassNotFoundException vs NoClassDefFoundError

자주 혼동되는 두 에러. 발생 시점이 다르다.

ClassNotFoundExceptionNoClassDefFoundError
종류Checked ExceptionError
발생 시점런타임에 동적으로 클래스 로딩 시도 시컴파일 시점에는 있었지만 런타임에 없을 때
원인Class.forName(), ClassLoader.loadClass() 실패클래스패스 누락, JAR 배포 누락
// ClassNotFoundException 발생 예시
try {
    Class.forName("com.example.NonExistentClass");
} catch (ClassNotFoundException e) {
    // 동적 로딩 실패
}

// NoClassDefFoundError 발생 예시
// 컴파일 시에는 SomeClass가 있었지만
// 런타임에 해당 JAR가 없는 경우 → JVM이 Error를 던짐
SomeClass obj = new SomeClass();

실무에서 만나는 클래스 로더 이슈

클래스 로더 누수 (메모리 누수의 일종)

웹 애플리케이션을 재배포(hot deploy)할 때 이전 클래스 로더가 GC되지 않으면 Metaspace OOM이 발생한다.

원인: ThreadLocal, static 필드 등에 이전 클래스 로더 참조가 남아있음
증상: 재배포를 반복하면 Metaspace 사용량이 계속 증가
해결: ThreadLocal.remove(), WeakReference 사용

Spring에서의 클래스 로딩

Spring Boot는 기본적으로 Application ClassLoader를 사용하지만, @Configuration의 CGLIB 프록시 생성이나 @Transactional AOP 프록시는 동적 클래스 생성을 활용한다. 이때 내부적으로 바이트코드 조작 라이브러리(ASM, CGLIB)를 사용한다.


관련 문서

  • JVM 구조
  • 바이트코드 조작 활용 예
java 카테고리의 다른 글 보기수정 제안하기

댓글

댓글을 불러오는 중...
목차
  • 클래스 로더 시스템
  • 클래스 로더 계층 구조
  • 부모 위임 모델 (Parent Delegation)
  • 클래스 로딩 3단계
  • 1. 로딩 (Loading)
  • 2. 링크 (Linking)
  • 3. 초기화 (Initialization)
  • ClassNotFoundException vs NoClassDefFoundError
  • 실무에서 만나는 클래스 로더 이슈
  • 클래스 로더 누수 (메모리 누수의 일종)
  • Spring에서의 클래스 로딩
  • 관련 문서