CS

CS 스터디 (Java) 3 - JVM 의 메모리 영역과 할당 시점은?

gentle-tiger 2025. 5. 13. 22:56

JVM(Java Virtual Machine)은 자바 프로그램 실행 시 운영체제로부터 메모리를 할당받아, 실행 목적에 따라 5가지 주요 영역으로 구분하여 관리합니다. 각 영역은 데이터의 종류와 생명주기에 따라 메모리 할당 시점이 다릅니다. 각 주요 영역 별로 설명하겠습니다. 

 

1. 메소드 영역

- 클래스 메타데이터, static 변수, 상수 풀(Run-Time Constant Pool), final 상수값 등이 저장됩니다.

- 클래스가 JVM에 처음 로딩될 때 메모리가 할당되며, 

- 모든 스레드가 공유하며, 프로그램 시작부터 종료까지 유지됩니다. 

- JDK 7까지는 PermGen(Permanent Generation), JVM 힙 내부에 고정 크기로 존재하여

- 많은 수의 클래스나 동적으로 로딩되는 클래스가 많은 경우 쉽게 가득 찼습니다.

- 이로 인해 OOM(OutOfMemoryError) 오류가 자주 발생하였으며, static 데이터를 사용하기 힘들었습니다.  

- 이를 해결하기 위해, JDK 8부터는 Metaspace로 대체되어 native memory에 위치하고, 크기를 동적으로 확장할 수 있게 되었습니다. 

 

** javap -v {클래스이름}.class 명령으로 클래스의 Constant Pool 확인 가능.

** Metaspace: JDK 8부터 PermGen을 대체한 영역으로, 역할은 동일하지만 JVM 힙이 아닌 native memory에 위치하며, 기본적으로 크기 제한이 없고 필요 시 자동 확장되는 장점이 있습니다.

 

 

2. 힙 영역

- new 연산자를 통해 생성된 모든 객체 인스턴스와 배열이 저장됩니다. 

- 런타임 시점, 즉 클래스 실행 중 객체 생성 시점에 동적으로 메모리가 할당됩니다. 

- 힙 영역은 GC(Garbage Collector)에 의해 관리되며, Young Generation(Eden, Survivor 0/1)Old Generation으로 나뉩니다.

- 모든 스레드가 공유합니다. 

String str1 = "abc";           // String Constant Pool (Heap의 일부)
String str2 = new String("abc"); // Heap 객체
System.out.println(str1 == str2); // false

- str1은 Constant Pool(Heap의 특수 영역)에 위치하고, str2는 일반 Heap 객체로 생성되어 서로 다른 참조값을 가지므로 false가 반환됩니다.

 

 

3. 스택 영역

- 메서드 호출 시 스택 프레임이 생성되고, 종료되면 종료되면 제거됩니다. 

- 스택 프레임에는 지역 변수, 매개변수, 리턴 주소 등이 저장되며, 

- 스레드마다 독립적으로 존재하며, LIFO(Last-In First-Out) 구조로 동작합니다. 

- 이 영역은 JVM이 자동으로 할당(push) 및 해제(pop)하기 때문에, GC의 관리 대상이 아닙니다.
(GC는 Heap처럼 객체 참조 여부를 추적하여 수집하지만, Stack은 스코프 기반으로 프레임 명확히 소멸되므로 GC가 필요하지 않습니다.)

 

 

4. PC 레지스터(PC Register)

- PC 레지스터는 현재 실행 중인 JVM 바이트코드 명령어의 주소를 저장합니다.

- 스레드가 시작될 때 초기화되며, JVM이 명령어 단위로 실행 흐름을 제어합니다. 

- 스레드마다 독립적으로 존재합니다. 

 

 

 

5. 네이티브 메서드 스택(Native Method Stack)

- JNI(Java Native Interface)를 통해 호출되는 C/C++ 등 네이티브 코드를 실행할 때 사용되는 스택입니다.

- 네이티브 메서드 호출 시 매개변수, 지역 변수 등이 저장됩니다. 

- 네이티브 메서드 스택은 스레드마다 존재하며, 필요 시 할당됩니다. 

 

JVM 메모리 영역별 역할 및 GC 관리 여부 정리

영역 저장 내용 할당 시점 공유 여부 GC 관리 대상
메소드 영역 클래스 메타데이터, static 변수 클래스 로딩 시 모든 스레드 공유 ❌(JDK 8 Metaspace는 GC 일부 관리)
힙 영역 객체, 배열, String Constant Pool 런타임 (new) 모든 스레드 공유
스택 영역 지역 변수, 매개변수 메서드 호출 시 스레드별
PC Register JVM 명령어 주소 스레드 시작 시 스레드별
네이티브 메서드 스택 네이티브 코드 실행 데이터 네이티브 메서드 실행 시 스레드별

 

결론 

JVM(Java Virtual Machine)의 메모리는 크게 5가지 주요 영역으로 구분됩니다. 각각의 영역은 목적에 따라 할당되는 시점이 다릅니다. 메소드 영역은 클래스 로딩 시 클래스의 메타 데이터, static 변수 상수 풀 등이 저장되는 영역으로, 클래스가 JVM에 처음 로딩 될 때 메모리 할당됩니다. 힙 영역은 애플리케이션에서 생성하는 모든 객체 인스턴스가 저장되는 영역으로 new 연산자를 통해 객체가 생성될 때마다 메모리가 동적으로 할당됩니다. 이 영역은 가비지 컬렉터의 관리 대상이며, 애플리케이션 성능에 큰 영향을 미칩니다. 스택 영역은 각 스레드마다 별도로 생성되며, 메서드가 호출될 때마다 스택 프레임이 생성되고, 메서드가 종료되면 프레임이 제거됩니다. 여기에는 지역 변수, 매개변수, 리턴 주소 등이 저장됩니다. 이 영역은 JVM이 자동으로 할당 및 해제되기 때문에 GC 대상이 아닙니다. PC Register는 현재 실행 중인 명령어의 주소를 저장하는 용도로 스레드마다 생성되며, 스레드가 시작될 때 초기화됩니다. Native Method Stack은 JNI(JAVA Native Interface)를 통해 호출되는 네이티브 메서드가 사용하는 스택으로, 스레드가 네이티브 코드를 실행할 때 할당됩니다.