자바(Java) 메모리 구조 / Runtime Data Area
자바의 메모리 구조
우리가 작성한 소스 코드는 컴파일해 자바 바이트 코드로 바꾸고 이를 JVM으로 실행하게 된다.
그리고 이 과정에서 코드들은 Runtime Data Area 영역에서 실행된다.
즉 OS가 JVM에 할당한 메모리 영역에 맞게 코드들이 분배되고 실행되는 것이라고 생각하면 된다.
Runtime Data Area
OS가 JVM에 할당해준 메모리 영역을 Runtime Data Area라고 부른다.
그리고 이러한 메모리 영역은 우선 크게 두 가지로 나뉜다.
쓰레드 별로 생성되는 메모리 영역과 모든 쓰레드가 공유하는 메모리 영역이다.
|
모든 쓰레드가 공유 |
Method Area |
Runtime Constant Pool |
|
Heap Area |
Eden |
|
|
Survivor 1 |
||
|
Survivor 2 |
||
|
Old |
||
|
Permanent |
||
|
쓰레드 별로 별도 생성 |
Stack Area |
|
|
PC Resisters |
||
|
Native Method Stack |
모든 쓰레드가 공유하는 메모리 영역
전체 쓰레드가 공유하는 메모리 영역은 JVM이 시작될 때 실행되고 JVM이 종료되면 해제가 된다.
1. Method Area (메서드 영역)
Class Area, Code Area, Static Area 등으로 불리는 해당 영역은 코드에서 사용되는 클래스 파일을 클래스로더로 읽어 클래스별로 런타임 상수풀, 필드 데이터, 메소드 데이터, 메소드 코드, 생성자 코드 등을 분류해서 저장한다.
이때 전역 변수와 정적 멤버 변수(static변수)는 이 영역에 저장되므로 프로그램이 시작부터 종료될 때까지 메모리 남아있게 되고, 이는 전역 변수가 프로그램 종료될 때까지 어디서든 사용이 가능한 이유가 된다.
Method Area에서 저장하는 데이터는 다음과 같다.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1-1. Runtime Constant Pool (런타임 상수 풀)
Method Area에 포함되며 클래스 파일 Constant_pool 테이블에 해당하는 영역이다.
- Type, Field, Method로의 모든 레퍼런스를 저장
- JVM은 Runtime Constant Pool을 통해 실제 메모리상 주소를 찾아 참조한다.
2. Heap Area(힙 영역)
JVM이 관리하는 프로그램에서 데이터를 저장하기 위해 런타임시 동적으로 할당하여 사용하는 영역
New연산자로 생성된 객체, 인스턴스와 배열을 저장한다.
힙 영역에 생성된 객체, 배열은 스택 영역의 변수나 다른 객체의 필드에서 참조한다.
참조하는 변수나 필드가 없으면 GC(가비지 콜렉터)의 대상이 된다.
힙 영역은 크게 5가지로 나뉜다.
|
Heap Area (힙 영역) |
|
|
|
|
|
|
|
|
|
쓰레드 별로 별도로 메모리가 생성되는 영역
쓰레드가 생성될 때 메모리 영역이 같이 생성되며, 쓰레드 종료되면 해제가 됨.
그래서 method나 heap에 비해 프로그램 내내 사용이 제한적일 수 밖에 없음.
1. Stack Area(스택 영역)
자바에서 메서드를 호출할 때 메서드의 Stack Frame이 저장되는 영역.
그리고 그 Stack Frame 안에는 지역변수, 인자값, 리턴값 등이 저장된다.
과정은 이렇다.
(1) 자바는 스레드를 생성하지 않았다면 main 스레드만 존재하고 그에 따라 stack frame도 한개만 있다.
(2) 그 과정에서 메서드를 호출하면 stack프레임을 하나 새로 생성(push)된다.
(3) 그리고 그 안에 메서드와 관계된 지역변수, 매개변수 등을 스택 영역에 저장한다.
(4) 이렇게 스택 영역은 메소드의 호출과 함께 할당되고 메소드의 호출이 완료되면 소멸(pop)한다.
Stack 영역에 저장되는 변수는 다음과 같다.
|
|
|
|
|
하지만 이는 실제 데이터가 아닌 참조값
|
소스코드를 만들 때 쓰는 기본 자료형(int, double, long, float) 등의 지역 변수는 Stack의 영역에 저장된다.
메서드 호출이 끝나면 Stack 내 메서드 관련 지역변수도 지워지기 때문에 지역 변수는 전역변수가 저장되는
Method 영역과 달리 메서드 영역 밖에서는 사용할 수 없는 것이다.
2. PC Resisters(PC 레지스터)
쓰레드가 하나씩 생성될 때 생기는 것으로 각 스레드마다 존재한다.
PC레지스터는 현재 실행중인 JVM의 명령 주소(Program Counter를 갖고 있는 영역이다.
CPU의 레지스터와는 별개로 Stack 내에서 작동하며, Native Stack을 실행할 땐 사용되지 않는다.
3. Native Stack(네이티브 스택)
Java 이외의 언어로 만들어진 코드들을 위한 Stack.
JNI(Java Native Interface)를 통해 호출되는 C / C++ 등의 코드를 수행하기 위한 Stack.
JVM 내부에 영향을 주지 않기 위해 따로 메모리 공간을 활용한다.