1. 들어가며
C, C++과 달리 자바는 자동 메모리 관리 메커니즘이 있다. 이에 메모리 누수나 오버플로 문제를 거의 겪지 않는다. 하지만 문제가 한번 터지면 JVM의 메모리 관리 방식을 이해하지 못하는 한 해결하기가 상당히 어렵다.
이번 장에서 JVM이 관리하는 다양한 메모리 영역을 알아보고, 각 영역이 수행하는 역할, 관리 대상, 생길 수 있는 문제를 알아보자.
2. 런타임 데이터 영역
JVM은 자바 프로그램을 실행하는 동안 필요한 메모리를 몇 개의 데이터 영역으로 나눠서 관리한다.

프로그램 카운터
- 프로그램 카운터 레지스터는 현재 실행중인 스레드의 바이트 코드 줄 번호 표시기다. 이 카운터 값을 바꿔가면서 다음에 실행할 바이트코드 명령어를 선택하는 식으로 동작한다.
- JVM에서 멀티스레딩은 CPU 코어를 여러 스레드가 교대로 사용하는 방식으로 구현되기 때문에 각 스레드의 카운터는 서로 영향을 주지 않는 독립적인 영역에 저장된다. → 스레드 프라이빗 메모리
- 한편 스레드가 네이티브 메서드를 실행중이라면 해당 값은 Undefined로 표시된다.
JVM 스택
- 스택도 스레드 프라이빗 메모리이며, 스레드와 라이프사이클이 동일하다. 스레드가 메모리를 호출할 때마다 JVM은 스택 프레임을 만들어 지역 변수, 피연산자 스택, 동적 링크, 리턴값 등을 저장한다.
- 스택은 보통 지역변수 테이블을 가리킬때가 가장 많다. 지역 변수 테이블에는 primitive type의 데이터, 객체 참조, 반환 주소 타입을 저장한다. 이 데이터 공간은 컴파일 과정에서 할당한다.
- 스택 용량을 동적으로 확장할 수 있는 JVM에서는 스택을 확장하려는 시점에 여유 메모리가 충분하지 않다면 OOM을 던진다.
네이티브 메서드 스택
- JVM 스택과 비슷하지만 네이티브 메모리를 실행할 때 사용하는 스택이다.
- 네이티브 메서드 스택과 JVM 스택을 합쳐놓은 가상 머신도 있다. (핫스팟 가상 머신 포함)