[자바] JVM Heap

Romy·2024년 1월 12일
0

자바

목록 보기
11/11
post-thumbnail


💭 생각해봅시다

JVM을 공부하면서, Heap에 대해서 더 자세하게 공부해야 전반적인 GC와 같은 개념들도 연계해서 더 이해할 수 있겠구나 싶어 Heap을 더 구체적으로 정리하게 되었습니다.


🔎 공부해봅시다

Heap 메모리란?

자바 프로그램이 실행되면서 동적으로 생성된 객체 (new 연산자로 생성된 객체) 가 저장되는 공간입니다. 이 곳에 생성된 객체들은 다른 메소드에 의해 참조될 수 있습니다. 참조하는 변수가 사라지면 이 객체는 필요없는 것으로 간주하고 Garbage Collector에 의해서 할당이 해제됩니다.

Heap 메모리 구조

힙 영역은 그 기능이 다양해서 여러 부분으로 나누어집니다. 객체가 처음 생성되면 저장되는 공간과 객체가 생성된 후 일정시간 사용되지 않으면 이동되어 가비지 컬렉션을 수행할 수 있도록 분류되는 공간으로 나누어서 관리합니다.

Heap 메모리 영역은 크게 3개의 영역으로 분리되어 있습니다. Eden, Survivor, Old 이렇게 3개로 나뉘어지며, 차례로 New → Young → Old 순서로 가비지 컬렉션이 진행되며 저장됩니다.

객체 저장 순서

  • 1️⃣ Eden → 2️⃣ Survivor → 3️⃣ Old

일단, 메모리에 객체가 생성되면 Eden 영역에 객체가 지정이 됩니다. Eden 영역의 데이터가 가득 차면 Eden 영역에 있던 객체가 Survivor1 혹은 Survivor2 로 옮겨집니다. (이때 참조가 없는 객체들은 Minor GC로 수집) 그리고 둘 중 하나의 영역이 가득 차게 되면 공간이 남아있는 Survivor로 이동하게 됩니다. S1 과 S2를 왔다갔다 하는 과정에서 오래 살아남은 객체들은 Old 영역으로 이동합니다. (Major GC가 이루어지며, Minor GC보다 횟수는 적게 발생)

⚠️ S1 또는 S2 둘 중 하나는 항상 비워있는 공간이 있는 채로 유지 됩니다.

⚠️ 보통 Old 영역은 Young 영역보다 크게 할당합니다.

  • 1️⃣ Eden → 2️⃣ Old

객체의 크기가 아주 클 경우, Surviovr 영역을 거치지 않고, 바로 Old 영역으로 넘어갑니다.

Java8 이후 Heap

위에 설명하지 않았지만, Heap 영역에는 Permanent Generation가 존재합니다. Permgen(Permanent Generation)은 Class 혹은 Method Code가 저장되는 영역입니다. JVM이 로드된 클래스의 메타데이터를 추적하는 기본 Java 힙과 별도의 특수한 힙 공간입니다.

Permgen를 따로 설명한 이유는, Java 8 이후로 사라졌기 때문입니다. 이전 Permgen 메모리 영역이 사라지고, 8 부터 Metaspace영역으로 변경되었습니다. Permgen과 Metaspace의 **가장 큰 차이는 Metaspace는 Permanent 과 달리 Heap 영역이 아닌 Native Memory 영역에 위치한다**는 점입니다. Metaspace 라는 영역으로 대체하였고, 이 Metaspace 영역은 Native 메모리 영역으로 JVM 이 아닌 OS 에 의해 관리되도록 변경되었습니다.


왜 이동했을까?

이전 Permanent에는 위와 같은 영역을 저장해두었습니다. 하지만 OOM 에러 (OutOfmemoryerror permgen space) 와 같이 permgen 에러가 발생하는 현상을 개선하기 위해 기존 permgen 영역에 저장되던 static object 를 heap 영역으로 이동시켰습니다. 결과적으로 static object 가 GC의 대상이 되도록 변경하고 메타데이터 정보들을 OS가 관리함으로써 사이즈 제한을 없앴습니다.


Metadata & Metaspace

  • Metaspace란?

Metaspace는 간단히 말해 Java의 Classloader가 로드한 class들의 metadata가 저장되는 공간입니다. 참고로, Metaspace 는 Native Area, Native Memory, Non-heap, Direct Memory 등과 같은 용어들과 혼용되어 쓰이기도 합니다. 모두 같은 것을 지칭하는 말이니 혼동하지 않으셔도 됩니다.

  • metadata

JVM process 안에 있는 Java class들의 runtime으로, 간단히 말해 JVM이 해당 class에 알아야하는 모든 정보입니다.

Metaspace로 변경됨으로써 metadata의 java.lang.class 와 같이 Object들은 Heap 안에 들어가서 GC 의 관리를 받게 되었습니다. Metadata의 예를 들면, java.lang.Class는 Java heap안에 사는 object지만, 그 class metadata는 Java object가 아니며 heap 안에 위치하지 않습니다. 이 metadata는 heap 외부의 native memory 구역에 위치하게 되었으며, 바로 이 구역이 Metaspace인 것입니다.


💡 정리해봅시다

Heap이란 동적으로 생성되는 객체가 저장되는 메모리입니다. Heap은 크게 Young New Old 3가지 영역으로 나뉘어 저장이 되고, 가비지 컬렉션에 따라 이동됩니다. new 연산자를 통해 생성된 객체는 가장 먼저 Young 영역의 Eden에 저장이 됩니다. 그리고 minor GC 에서 살아남은 객체들은 Young 영역인 Survior에 저장이되고 Survivor은 1과 2가 있는데 순서에 상관없이 저장되어 서로 왔다갔다 하며 GC가 진행되딥니다. Major GC에서 살아남은 객체는 Young 영역에서 Old 영역에 저장이 됩니다.

또한, Java8 이후부터 Heap 메모리 구조에 변경이 생겼습니다. 이전 Permanent Generation 메모리 영역이 Heap에 포함되었지만 이 영역이 Heap에서 사라지고, Java8부터 Metaspace영역으로 변경되었습니다. 또한, 이 Metaspace 영역은 Native 메모리 영역으로 JVM 이 아닌 OS 에 의해 관리되도록 변경되었습니다.


참고

https://jaemunbro.medium.com/java-metaspace에-대해-알아보자-ac363816d35e

profile
👩‍💻 IT Engineering

0개의 댓글