본문 바로가기

백엔드 CS 정리

JVM 내부 동작 원리

1. Java 프로그램 실행 과정

  1. Java 소스 코드 작성 및 실행
    • 개발자가 Java 소스 코드를 작성하고, Run 명령을 실행하면 Javac 컴파일러가 소스 코드를 바이트 코드(.class 파일)로 변환한다.
  2. JVM의 역할
    • JVM(Java Virtual Machine)은 바이트 코드를 읽고 실행하는 가상 머신이다.
      • 이때, Class Loader를 통해 .class 파일을 JVM 내부로 로드하고, Runtime Data Area에 배치한 후, Execution Engine이 이를 실행한다.

2. JVM의 주요 구성 요소

2.1 Class Loader (클래스 로더)

  • 역할: .class 파일(바이트 코드)을 JVMRuntime Data Area로 로드하고, 클래스 간의 참조를 연결하는 작업을 수행한다.
    • 로딩(Loading): .class 파일을 읽고 메모리에 로드한다.
    • 링크(Linking): 클래스 간의 의존성을 확인하고 준비(Preparation)한다.
    • 초기화(Initialization): 클래스 변수들을 초기화하고, 초기화 메서드 실행을 통해 Runtime Data Area에 배치한다.

2.2 Runtime Data Area (실행 시 데이터 영역)

  • JVM이 프로그램 실행 시 필요한 데이터를 저장하는 메모리 영역이다.
  • Runtime Data Area는 다음의 영역들로 구성된다:
    1. Method Area (메소드 영역)
      • 역할: 클래스에 대한 구조 정보(메서드, 변수, 상수 풀 등)를 저장하는 공간.이곳에 저장된 정보는 모든 JVM 스레드에서 공유된다.
      • 저장되는 데이터:
        • 클래스 정보 (필드, 메서드, 상수 풀)
        • 스태틱 변수
    2. Heap Area (힙 영역)
      • 역할: new 연산자로 생성된 객체와 배열이 저장되는 공간.모든 스레드에서 공유되며, GC(Garbage Collector)가 관리한다.
    3. Stack Area (스택 영역)
      • 역할: 각 스레드가 사용하는 스택으로, 메서드 호출 시마다 스택 프레임이 생성되며 로컬 변수, 메서드 매개변수, 리턴값 등을 저장한다.
      • 저장되는 데이터:
        • 로컬 변수, 메서드 호출 정보, 리턴 주소
    4. PC Register (프로그램 카운터 레지스터)
      • 역할: 현재 실행 중인 JVM 스레드의 명령 주소를 저장하는 공간.각 스레드마다 하나씩 할당된다.
    5. Native Method Stack (네이티브 메소드 스택)
      • 역할: Java 외의 언어로 작성된 네이티브 메서드가 실행될 때 사용되는 스택 공간.예를 들어, C/C++로 작성된 메서드들이 호출되었을 때 저장된다.

2.3 Execution Engine (실행 엔진)

  • 역할: Runtime Data Area에 있는 바이트 코드를 실행한다.
    1. Interpreter (인터프리터) 방식
      • 바이트 코드를 명령어 단위로 한 줄씩 해석하고 실행한다.
      • 장점: 빠른 실행 시작
      • 단점: 전체 프로그램을 실행하는 속도가 느림
    2. JIT (Just-In-Time) 컴파일러 방식
      • 자주 사용되는 코드(핫스팟)를 발견하면, 해당 코드를 바이트 코드에서 기계어로 변환하여 캐싱하고 이후에는 기계어로 실행한다.
      • 장점: 반복적인 코드 실행 시 속도 향상
  • Execution Engine은 다음 두 가지 방식을 사용한다:

2.4 Garbage Collector (가비지 컬렉터)

  • 역할: 더 이상 사용되지 않는 객체를 메모리에서 자동으로 해제하는 기능을 수행한다.
  • GC의 주요 작업:
    • 힙 영역을 관리하며, 사용되지 않는 객체를 찾아 제거함으로써 메모리 누수를 방지한다.

3. JVM 동작의 전체 흐름

  1. Java 소스 코드Javac 컴파일러에 의해 바이트 코드(.class 파일)로 변환된다.
  2. Class Loader바이트 코드Runtime Data Area로 로드한다.
  3. Runtime Data Area에 로드된 바이트 코드는 Execution Engine에 의해 해석되고 실행된다.
    • 이때 인터프리터JIT 컴파일러가 혼합된 방식으로 바이트 코드를 실행한다.
  4. Garbage Collector가 주기적으로 힙 메모리를 관리하고, 더 이상 필요 없는 객체를 제거한다.

'백엔드 CS 정리' 카테고리의 다른 글

JAVA에서 Final을 사용하는 이유  (0) 2024.09.30
쿠키 vs 세션 vs 캐시  (1) 2024.09.24
Bcrypt를 사용하는 이유  (1) 2024.09.22