1. Java 프로그램 실행 과정
- Java 소스 코드 작성 및 실행
- 개발자가 Java 소스 코드를 작성하고, Run 명령을 실행하면 Javac 컴파일러가 소스 코드를 바이트 코드(.class 파일)로 변환한다.
- JVM의 역할
- JVM(Java Virtual Machine)은 바이트 코드를 읽고 실행하는 가상 머신이다.
- 이때, Class Loader를 통해 .class 파일을 JVM 내부로 로드하고, Runtime Data Area에 배치한 후, Execution Engine이 이를 실행한다.
- JVM(Java Virtual Machine)은 바이트 코드를 읽고 실행하는 가상 머신이다.
2. JVM의 주요 구성 요소
2.1 Class Loader (클래스 로더)
- 역할: .class 파일(바이트 코드)을 JVM의 Runtime Data Area로 로드하고, 클래스 간의 참조를 연결하는 작업을 수행한다.
- 로딩(Loading): .class 파일을 읽고 메모리에 로드한다.
- 링크(Linking): 클래스 간의 의존성을 확인하고 준비(Preparation)한다.
- 초기화(Initialization): 클래스 변수들을 초기화하고, 초기화 메서드 실행을 통해 Runtime Data Area에 배치한다.
2.2 Runtime Data Area (실행 시 데이터 영역)
- JVM이 프로그램 실행 시 필요한 데이터를 저장하는 메모리 영역이다.
- Runtime Data Area는 다음의 영역들로 구성된다:
- Method Area (메소드 영역)
- 역할: 클래스에 대한 구조 정보(메서드, 변수, 상수 풀 등)를 저장하는 공간.이곳에 저장된 정보는 모든 JVM 스레드에서 공유된다.
- 저장되는 데이터:
- 클래스 정보 (필드, 메서드, 상수 풀)
- 스태틱 변수
- Heap Area (힙 영역)
- 역할: new 연산자로 생성된 객체와 배열이 저장되는 공간.모든 스레드에서 공유되며, GC(Garbage Collector)가 관리한다.
- Stack Area (스택 영역)
- 역할: 각 스레드가 사용하는 스택으로, 메서드 호출 시마다 스택 프레임이 생성되며 로컬 변수, 메서드 매개변수, 리턴값 등을 저장한다.
- 저장되는 데이터:
- 로컬 변수, 메서드 호출 정보, 리턴 주소
- PC Register (프로그램 카운터 레지스터)
- 역할: 현재 실행 중인 JVM 스레드의 명령 주소를 저장하는 공간.각 스레드마다 하나씩 할당된다.
- Native Method Stack (네이티브 메소드 스택)
- 역할: Java 외의 언어로 작성된 네이티브 메서드가 실행될 때 사용되는 스택 공간.예를 들어, C/C++로 작성된 메서드들이 호출되었을 때 저장된다.
- Method Area (메소드 영역)
2.3 Execution Engine (실행 엔진)
- 역할: Runtime Data Area에 있는 바이트 코드를 실행한다.
- Interpreter (인터프리터) 방식
- 바이트 코드를 명령어 단위로 한 줄씩 해석하고 실행한다.
- 장점: 빠른 실행 시작
- 단점: 전체 프로그램을 실행하는 속도가 느림
- JIT (Just-In-Time) 컴파일러 방식
- 자주 사용되는 코드(핫스팟)를 발견하면, 해당 코드를 바이트 코드에서 기계어로 변환하여 캐싱하고 이후에는 기계어로 실행한다.
- 장점: 반복적인 코드 실행 시 속도 향상
- Interpreter (인터프리터) 방식
- Execution Engine은 다음 두 가지 방식을 사용한다:
2.4 Garbage Collector (가비지 컬렉터)
- 역할: 더 이상 사용되지 않는 객체를 메모리에서 자동으로 해제하는 기능을 수행한다.
- GC의 주요 작업:
- 힙 영역을 관리하며, 사용되지 않는 객체를 찾아 제거함으로써 메모리 누수를 방지한다.
3. JVM 동작의 전체 흐름
- Java 소스 코드는 Javac 컴파일러에 의해 바이트 코드(.class 파일)로 변환된다.
- Class Loader가 바이트 코드를 Runtime Data Area로 로드한다.
- Runtime Data Area에 로드된 바이트 코드는 Execution Engine에 의해 해석되고 실행된다.
- 이때 인터프리터와 JIT 컴파일러가 혼합된 방식으로 바이트 코드를 실행한다.
- Garbage Collector가 주기적으로 힙 메모리를 관리하고, 더 이상 필요 없는 객체를 제거한다.
'백엔드 CS 정리' 카테고리의 다른 글
JAVA에서 Final을 사용하는 이유 (0) | 2024.09.30 |
---|---|
쿠키 vs 세션 vs 캐시 (1) | 2024.09.24 |
Bcrypt를 사용하는 이유 (1) | 2024.09.22 |