Programing Language/JAVA

JVM (Java Virtual Machine) 구조 상세 설명

칼쵸쵸 2025. 7. 31. 22:12

JVM은 **자바 바이트코드(.class 파일)**를 실행하기 위한 가상 머신이에요.
구조적으로는 크게 클래스 로더, 런타임 데이터 영역, 실행 엔진, 네이티브 인터페이스로 나뉘어요.


1️⃣ 클래스 로더 (Class Loader Subsystem)

  • 역할: .class 파일(바이트코드)을 메모리로 적재해서 런타임 영역에 올림
  • 동적 로딩(Dynamic Loading): 실행 중 필요한 클래스만 메모리에 로드
  • 주요 단계
    1. Loading
      • 클래스 파일을 읽어 Method Area에 로드
    2. Linking
      • Verification: 바이트코드가 JVM 규격에 맞는지 검사
      • Preparation: static 변수에 메모리 할당 & 기본값 초기화
      • Resolution: 심볼릭 참조(클래스명, 메소드명 등)를 실제 메모리 주소로 변경
    3. Initialization
      • static 변수와 static 블록 실행

2️⃣ 런타임 데이터 영역 (Runtime Data Area)

JVM 프로세스 안에서 데이터를 저장하고 관리하는 메모리 영역이에요.

📍 [공유 영역 - 모든 스레드가 공유]

  1. Method Area (또는 MetaSpace, JDK 8 이후)
    • 클래스 구조, 메소드, 상수 풀, static 변수 저장
    • JDK 8 이전에는 PermGen 영역이었으나, 이후 MetaSpace로 교체 (네이티브 메모리 사용)
  2. Heap Area
    • 모든 객체 인스턴스와 배열이 저장되는 영역
    • GC의 주요 대상
    • 세분화 구조
      • Young Generation
        • Eden Space: 새로 생성된 객체
        • Survivor Space (S0/S1): GC에서 살아남은 객체 이동
      • Old Generation (Tenured): 여러 번 GC를 거쳐 살아남은 장수 객체
    • Heap은 JVM 성능 튜닝의 핵심 (-Xmx, -Xms)

📍 [스레드별 영역 - 각 스레드마다 생성]

  1. PC Register (Program Counter Register)
    • 현재 실행 중인 JVM 명령어의 주소 보관
  2. JVM Stack
    • 메서드 호출 시 생성되는 Frame 저장
    • Frame 구조
      • Local Variables Array: 매개변수 & 지역변수
      • Operand Stack: 연산 중간 결과
      • Frame Data: 메서드/클래스 정보, Exception 처리기 등
    • 스레드 종료 시 스택도 함께 제거
  3. Native Method Stack
    • JNI (Java Native Interface)로 호출되는 C/C++ 같은 네이티브 코드용 스택

3️⃣ 실행 엔진 (Execution Engine)

클래스 로더가 적재한 바이트코드를 실제로 실행하는 부분

  1. 인터프리터
    • 바이트코드를 한 줄씩 해석 후 실행
    • 빠른 시작 가능하지만 실행 속도는 느림
  2. JIT 컴파일러 (Just-In-Time Compiler)
    • 자주 실행되는 바이트코드를 기계어로 변환 후 캐시
    • 이후에는 인터프리팅 없이 네이티브 코드 실행
    • HotSpot JVM의 핵심 성능 최적화
  3. Garbage Collector (GC)
    • Heap 영역의 불필요한 객체 자동 해제
    • 대표 알고리즘
      • Serial GC (단일 스레드)
      • Parallel GC (여러 스레드 병렬 수집)
      • CMS (Concurrent Mark-Sweep) → JDK 9부터 deprecated
      • G1 GC (Garbage-First) → 대용량 Heap에 유리
      • ZGC, Shenandoah → 초저지연 목적

4️⃣ 네이티브 인터페이스 (JNI)

  • Java에서 네이티브 라이브러리(C/C++)를 호출할 수 있게 하는 인터페이스
  • OS API나 고성능 라이브러리 호출 시 사용
  • Native Method Libraries와 연동

⚙️ 실행 흐름 예시

[.java 파일] → javac → [.class 파일]
         ↓
    Class Loader
         ↓
   Runtime Data Area
         ↓
   Execution Engine
     ↳ Interpreter & JIT
     ↳ GC 관리
         ↓
   Native Interface
         ↓
       OS / 하드웨어

 


📌 성능/튜닝 포인트

  1. Heap 크기 조정
    • -Xmx / -Xms
  2. GC 알고리즘 선택
    • 대규모 데이터 처리 시 G1GC, 저지연 필요 시 ZGC
  3. Thread Stack 크기
    • -Xss 옵션
  4. Metaspace 크기
    • -XX:MaxMetaspaceSize
  5. JIT Warm-up 시간 고려
    • 서버 앱은 장시간 실행 시 JIT 최적화 효과 큼

✅ 요약
JVM은

  • 클래스 로더로 바이트코드를 메모리에 올리고
  • 런타임 데이터 영역에서 객체와 스레드별 메모리를 관리하며
  • 실행 엔진이 인터프리터 & JIT & GC를 통해 코드를 실행하고
  • 필요 시 JNI로 네이티브 코드와 통신

 

반응형