자바 가상 머신(JVM) 이란?
JVM(Java Virtual Machine)은 자바 프로그램을 다양한 운영체제에서 실행할 수 있게 해주는 가상 머신입니다. 자바 프로그램은 기계어 대신 바이트코드라는 중간단계 코드로 변환되는데, 운영체제가 이를 직접 실행할 수 없기 때문에 바이트코드를 해석하고 실행하는 역할을 하는 것이 바로 JVM입니다. 또한 JVM은 Thread 관리 및 Garbage Collection과 같은 메모리 작업도 수행합니다.
JVM은 특정 운영체제와 하드웨어 환경에 맞춘 기계어로 바이트코드를 변환하므로 운영체제에 종속적입니다. 따라서 자바 개발 키트(JDK)나 자바 런타임 환경(JRE)을 설치할 때 운영체제에 맞는 JVM이 함께 제공됩니다.
JVM 구조
JVM은 다음과 같은 구성 요소로 이루어져 있으며, 각 구성 요소는 JVM이 자바 프로그램을 효율적으로 실행하는 데 중요한 역할을 수행합니다.
1. 클래스 로더 (Class Loader)
클래스 로더는 자바 프로그램을 실행하기 위해 바이트코드를 메모리에 로딩하는 역할을 합니다. 클래스 파일을 찾아서 JVM에 로드하고, 필요한 의존성 클래스를 불러와 프로그램이 정상적으로 실행되도록 돕습니다.
2. 런타임 데이터 영역 (Runtime Data Area)
Runtime Data Area는 JVM이 OS으로부터 할당 받은 메모리 공간입니다. JVM은 힙, 스택, 메소드 영역으로 메모리를 분리하여 효율적으로 관리하며 이렇게 분리된 메모리 구조 덕분에 프로그램 실행 중 필요한 데이터나 객체를 효과적으로 저장하고 접근할 수 있습니다.
메소드(Method) 영역
메소드 영역은 코드에서 사용되는 클래스들을 클래스 로더로 읽어 클래스, 변수, Method, static 변수, 상수 정보 등으로 분류되어 저장되며 JVM이 시작할 때 생성되고 모든 스레드가 공유하는 영역입니다.
힙(Heap) 영역
힙 영역은 객체와 배열이 생성되는 영역으로 힙 영역에 생성된 객체와 배열은 JVM의 스택 영역의 변수나 다른 객체의 필드에서 참조합니다. 만약 참조하는 변수나 필드가 없다면 의미 없는 객체가 되기 때문에 GC(Garbage Collector)에 의해 제거됩니다. 모든 스레드가 공유하는 영역입니다.
스택(Stack) 영역
스택 영역은 각 스레드마다 하나씩 존재하며 스레드가 시작될 때 할당됩니다. 기본 타입(boolean, char, byte, short, int, long, float, double)의 값과 변수를 저장하고, 참조 타입의 변수와 힙 영역이나 메소드 영역의 객체 주소를 저장합니다.
참고로 기본 타입 변수는 변수와 값을 전부 스택영역에서 갖고 있지만 참조 타입 변수의 경우에는 변수(name, hobby)는 스택 영역에서, 값("key", "독서")은 힙 영역에서 갖고 스택 영역의 변수가 힙 영역의 값의 메모리 주소를 갖고 참조합니다.
// 기본 타입 변수
int age = 25;
double price = 100.5;
// 참조 타입 변수
String name = "key";
String hobby = "독서";
PC register
PC register는 각 Thread가 시작될 때 생성되며 Thread마다 하나씩 존재합니다. 현재 실행중인 부분의 상태 정보와 주소를 저장하는 영역입니다.
Native Method Stack
Native Method Stack은 Java가 아닌 다른 언어로 작성된 코드를 위한 영역으로 바이트코드가 아닌 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역입니다. 마찬가지로 Thread 별로 생성된다는 특징이 있습니다.
3. 실행 엔진(Execution Engine)
실행 엔진은 실제로 바이트코드를 해석하고 실행하는 엔진입니다. 인터프리터와 JIT 컴파일러로 이루어져 있으며, 때문에 자바는 컴파일 언어이면서도 인터프리터 언어의 특성을 함께 가지고 있습니다.
- 인터프리터: 바이트코드를 한 줄씩 해석하고 실행합니다. 속도가 느리다는 단점이 있습니다.
- JIT 컴파일러: 인터프리터의 단점을 보완하기 위해 자주 호출되는 메서드를 기계어로 미리 변환하여 실행 속도를 높입니다.
4. 가비지 컬렉터 (Garbage Collector)
가비지 컬렉터, GC는 사용하지 않는 메모리를 자동으로 회수하여 메모리 누수(Memory Leak)를 방지합니다. 개발자가 직접 메모리 관리를 해줘야하는 C 언어와 달리 자바에서는 가비지 컬렉터가 주기적으로 힙 영역에서 불필요한 객체를 제거합니다. 이 기능 덕분에 개발자는 메모리 관리에 집중하지 않고 애플리케이션 로직에 집중할 수 있습니다.
JVM 동작 순서
1. 어플리케이션이 실행되면 JVM이 OS로부터 메모리를 할당 받습니다.
2. JAVA 컴파일러(javac.exe)가 자바 소스 파일(.java)을 바이트 코드(.class)로 변환합니다.
3. 변환된 바이트 코드가 클래스 로더를 통해 JVM으로 로드됩니다.
4. 로드된 바이트코드는 Execution Engine(실행엔진)에 의해 해석됩니다.
5. 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 실행됩니다.
'Java' 카테고리의 다른 글
[Java] 추상 클래스란 무엇인가? (0) | 2024.10.30 |
---|---|
[Java] 객체 지향 프로그래밍(OOP)의 4가지 특징과 원칙(SOLID) (0) | 2024.10.29 |
[Java] 이것이 자바다 - 상속 (1) | 2023.07.04 |
[Java] 인접행렬, 인접리스트 (0) | 2023.02.28 |
[Java] 정적 멤버와 static (0) | 2023.02.23 |