JVM 아키텍처 정리 및 실행 메모리 구조(Stack, Heap, Static)
Java 프로그램은 단순히 코드를 작성하고 실행하는 것이 아니라, 내부적으로 JVM(Java Virtual Machine) 이라는 가상 머신을 통해 실행됩니다. JVM은 Java 코드가 플랫폼 독립적으로 실행될 수 있도록 해주는 핵심 요소로, 다양한 컴퓨터 환경에서 동일하게 동작할 수 있도록 설계되었습니다.
이번 글에서는 JVM 아키텍처의 주요 구성 요소와 함께, JVM 메모리 구조인 Stack, Heap, Static 영역에 대해 자세히 알아보겠습니다.
1. JVM 아키텍처 개요
JVM은 크게 Class Loader, Runtime Data Area, Execution Engine, Native Interface 로 구성됩니다.
1) Class Loader (클래스 로더)
.class
파일을 읽고 메모리에 적재하는 역할을 합니다.
- 클래스를 로드하는 과정은 로딩(Loading) → 링크(Linking) → 초기화(Initialization) 로 이루어집니다.
- 클래스 로더에는 Bootstrap Class Loader, Extension Class Loader, Application Class Loader 가 있습니다.
2) Runtime Data Area (실행 데이터 영역)
- JVM이 실행될 때 필요한 메모리 영역을 관리합니다.
- 주요 영역: Method Area(메서드 영역), Heap(힙), Stack(스택), PC Register(PC 레지스터), Native Method Stack(네이티브 메서드 스택)
3) Execution Engine (실행 엔진)
- 바이트코드를 실제 기계어로 변환하여 실행합니다.
- Interpreter(인터프리터): 한 줄씩 바이트코드를 해석하여 실행
- JIT(Just-In-Time) Compiler: 반복적으로 실행되는 코드를 기계어로 변환하여 성능 향상
- Garbage Collector(GC): 필요 없는 객체를 자동으로 정리하여 메모리 관리
4) Native Interface (네이티브 인터페이스)
- 자바 코드가 네이티브 코드(C, C++ 등)와 상호 작용할 수 있도록 지원합니다.
- 대표적으로
JNI(Java Native Interface)
를 통해 네이티브 라이브러리를 호출할 수 있습니다.
2. JVM 메모리 구조(Stack, Heap, Static)
JVM에서 실행되는 프로그램은 여러 가지 메모리 영역을 사용합니다. 그중에서도 중요한 Stack, Heap, Static 영역을 살펴보겠습니다.
1) Stack (스택 영역)
- 메서드 호출 시 생성되는 메모리 공간 으로, 각 메서드는 자신의 스택 프레임(Stack Frame)을 가집니다.
- 지역 변수, 매개변수, 리턴값, 연산 중간 결과 등이 저장됩니다.
- 메서드가 호출되면 스택 프레임이 쌓이고, 종료되면 제거됩니다.
StackOverflowError
가 발생할 수 있으며, 재귀 호출이 너무 깊어지면 발생하는 대표적인 오류입니다.
예제 코드 (Stack 메모리 사용)
public class StackExample {
public static void main(String[] args) {
int result = factorial(5);
System.out.println(result);
}
public static int factorial(int n) {
if (n == 1) return 1;
return n * factorial(n - 1);
}
}
factorial(5)
호출 시 스택 프레임이 계속 쌓였다가 반환되면서 하나씩 제거됩니다.
2) Heap (힙 영역)
- 객체(Instance)가 저장되는 동적 메모리 공간 입니다.
new
키워드로 생성된 객체는 Heap에 할당되며, GC(Garbage Collector)가 필요 없어진 객체를 자동으로 제거 합니다.
- Heap 영역은 Young Generation(새로운 객체), Old Generation(오래된 객체) 로 구분되어 관리됩니다.
예제 코드 (Heap 메모리 사용)
class Person {
String name;
Person(String name) {
this.name = name;
}
}
public class HeapExample {
public static void main(String[] args) {
Person p1 = new Person("Alice"); // Heap에 객체가 생성됨
Person p2 = new Person("Bob"); // 새로운 객체 생성
}
}
new Person("Alice")
,new Person("Bob")
은 모두 Heap에 저장됩니다.
- 참조 변수가 없어지면 GC가 객체를 자동으로 제거합니다.
3) Static (메서드 영역)
- 클래스 정보, static 변수, static 메서드, 상수 풀 등이 저장되는 공간입니다.
- 프로그램이 시작될 때 메모리에 할당되며, 종료될 때까지 유지됩니다.
예제 코드 (Static 메모리 사용)
class StaticExample {
static int count = 0;
public StaticExample() {
count++;
}
public static void main(String[] args) {
StaticExample s1 = new StaticExample();
StaticExample s2 = new StaticExample();
System.out.println(StaticExample.count); // 2
}
}
count
변수는static
으로 선언되었으므로 클래스가 로드될 때 메모리에 올라가고, 프로그램이 종료될 때까지 유지됩니다.
3. Stack vs Heap vs Static 영역 비교
메모리 영역 | 특징 | 저장되는 데이터 |
Stack | 메서드별로 생성 및 제거 | 지역 변수, 매개변수, 리턴 값 |
Heap | 동적으로 생성되는 객체 저장 | 객체, 인스턴스 변수 |
Static | 프로그램 종료 전까지 유지 | 클래스 정보, static 변수, 상수 |
4. 마무리
JVM 아키텍처는 Java 프로그램이 실행되는 구조를 이해하는 데 매우 중요한 요소입니다. 특히, Stack, Heap, Static 영역의 역할을 명확히 이해하면, 효율적인 메모리 관리를 할 수 있습니다.
핵심 정리
✅ JVM은 Class Loader, Runtime Data Area, Execution Engine, Native Interface로 구성된다.
✅ Stack은 메서드 실행과 함께 생성되는 임시 메모리 공간이며, 지역 변수를 저장한다.
✅ Heap은 객체가 저장되는 영역으로, Garbage Collector가 메모리를 관리한다.
✅ Static 영역은 프로그램이 종료될 때까지 유지되는 클래스 정보 및 static 변수를 저장한다.
Share article