JVM의 메모리 영역으로, 자바 애플리케이션을 실행할 때 사용되는 데이터를 적재하는 역할을 수행한다.
: 바이트 코드(
.class
)를 처음 메모리 공간에 올릴 때, 초기화 되는 대상을 저장하기 위한 메모리 공간
= 프로그램 실행 중 클래스나 인터페이스를 사용하게 되면, JVM은 Class Loader을 이용해 클래스나 인터페이스의 Meta data를 Method Area에 저장한다.
정적(Static) 영역이라고도 부른다.
모든 Thread에 의해 공유되는 영역이다.
Runtime Constant Pool 영역을 가진다.
클래스/인터페이스의 메서드, 필드, 문자열 상수 등의 레퍼런스가 저장되며, 이들의 물리적 메모리 위치를 참조할 경우 사용된다.
JVM에서
동적
으로 할당된 모든 객체와 배열을 저장하며, 객체의 생명주기를 관리하는 메모리 공간
[ Heap 영역 내 객체의 LifeCycle ]
- Minor GC: Eden 영역 또는 Survivor 1, 2 등 Young 영역에서 발생하는 GC
- Major GC : Old 영역에서 발생하는 GC
프로그램이 실행될 때(Runtime) 생성되어 종료될 때 해제된다.
Heap 영역에 저장된 객체(인스턴스)나 배열을 다른 객체에서 참조될 수 있다.
Garbage Collector(GC)가 발생하는 영역이며, 참조가 없는 객체들은 GC에 의해 메모리에서 해제된다.
JVM 제품(벤더)에 따라 구현이 다르다. Hotspot JVM
(Oracle)의 Mteho Area는 Permanent Area(Perm Area, ~Java 7
) → MetaSpace Area(Java 8
~)이라고 한다.
: 새로 생성된 대부분의 객체가 처음 위치하는 영역
: Survivor 1 또는 2 중 하나의 영역이 가득 차게 되면, 그 중 살아남은 객체가 비워진 Survivor 영역으로 이동하게 된다.
이 때, 참조가 없는 개체들은 메모리에서 정리된다.
위의 메커니즘으로, Survivor 1 또는 2는 항상 비워진 상태여야 하며,
둘 중 하나의 영역이 완전히 비워져 있지 않다면, 문제가 있는 것이다.
Minor GC에서 살아남아 Survivor로 이동할 때마다 객체의 Age가 증가하며,
일정 값을 넘게 되면, Old 영역으로 이동하게 된다. (Promotion
)
Promotion의 기준이 되는 Age 값은 `Java SE8` 기준 15이며, 사용자가 임의로 조정할 수 있다. ( 0~15 )
: Survivor 1 또는 2를 왔다갔다 하는 과정에서 끝까지 살아남은 객체는 Old 영역으로 이동하게 된다.
Old 영역은 Young 영역에 비해 크게 할당된다.
Young 영역에 비해 GC가 적게 발생한다.
가득 차게 되면 기본적으로 GC가 발생하게 되며, GC 방식에 따라 절차가 달라진다.
: 현재까지 로드된 Class와 Method의 Meta data, Static 변수와 상수 정보들이 저장되는 공간
<----- Java Heap -----> <--- Native Memory --->
+------+----+----+-----+-----------+--------+--------------+
| Eden | S0 | S1 | Old | Permanent | C Heap | Thread Stack |
+------+----+----+-----+-----------+--------+--------------+
<--------->
Permanent Heap
S0: Survivor 0
S1: Survivor 1
현재까지 로드한 Class와 Method의 Meta data가 저장되는 공간
<----- Java Heap -----> <--------- Native Memory --------->
+------+----+----+-----+-----------+--------+--------------+
| Eden | S0 | S1 | Old | Metaspace | C Heap | Thread Stack |
+------+----+----+-----+-----------+--------+--------------+
ArrayList와 같은 Reference 타입의 동적 배열 객체를
static
으로 생성하게 되면, Permanent 영역에 저장하게 된다.
이 때, 해당 객체 배열의 원소를 추가하면 그대로static Object
의 레퍼런스가 Parmanent 영역에 쌓임과 함께
String Literal Data를 저장하던 String Pool도 Permanent 영역에 저장하느라 OOM Error(OutOfMemory Error
) 이슈가 잦았다고 한다.
: JVM에서 관리하는 Heap이 아닌 OS 레벨에서 관리되는 Native 메모리 영역을 사용함으로서 개발자는 영역 확보의 상한을 크게 의식할 필요가 없어지게 되었다.
: 참조가 있으면, GC의 대상이 되지 않는다.
Metaspace에 static object의 참조를 보관함으로써 참조 중엔 GC의 대상이 되는 것을 피하고, static object는 heap에 저장시켜 OOM이 일어났던 Perment 영역 때와는 달리 참조가 없을 땐 GC가 일어나도록 한다.
오늘은 Java 7 -> 8로 변경되며 생긴 Metaspace 부분이 가장 어려웠다.
열심히 설명한 글이 있는데, 잘 이해가 되지 않는다. 내가 이해한 내용이 맞기를..
아직 공부할 게 태산이라, 모르는 내용 나왔다고 그 쪽 파다가 방향을 잃기 쉽상이니 조심하자
[메모리] JVM의 메모리 사용 방식 : JVM의 Static Area와 Heap Area를 중심으로 Kotlin/JVM의 메모리 사용방식을 이해하기
Java Memory 간단히 살펴보기 - J's log