728x90

이번에는 Heap의 구조와 가비지 컬렉터에 대해 알아보자.

 


Heap의 구조

Heap은 객체를 저장하는 가상 메모리 공간이다.

'객체는 대부분 일회성이며, 메모리에 오랫동안 남아있는 경우는 드물다' 라는 전제로 객체의 생존 기간에 따라 Heap의 영역을 나누었다.

 

Heap에는 원래 3가지 영역이 있는데,

1. New/Young Generation

2. Old Generation

3. Permanent Generation

이 세가지 중 Permanent Generation은 JAVA 8부터 삭제된 영역이다.

 

Heap - Permanent Generation

생성된 객체들의 정보의 주소값이 저장된 공간이다.

Class Loader에 의해 로드되는 클래스, 메서드에 대한 메타 정보가 저장된다. 

앞서 말했다싶이 JAVA 8때부터는 삭제되고, Metaspace로 교체되었다. 

 

Heap - New/Young Generation

새롭게 생성된 객체가 할당되는 영역이다.

Eden : 객체들이 최초로 생성되는 공간

Survivor 0,1 :  Eden에서 참조되는 객체들이 저장되는 공간, 최소 1번의 GC 이상 살아남은 객체가 존재하는 영역

New/Young 부분에 대한 GC를 Minor GC라고 하는데, 이 부분은 조금 이따가 더 자세히 알아보도록 하자.

 

Heap - Old Generation

일정시간 이상 참조되고 있는, 살아남은 객체들이 저장되는 공간이다.

Old 부분에 대한 GC를 Major 또는 Full GC라고 한다. 

 


가비지 컬렉션(GC)

참조되지 않는 객체들을 탐색 후 삭제한다.

삭제된 객체의 메모리를 반환하여 Heap 메모리의 재사용을 할 수 있게 해준다.

 

가비지 컬렉션의 과정

  1. Heap내의 객체 중 가비지를 찾아낸다 (Marking)
    1. 모든 오브젝트를 탐색하기 때문에 시간이 오래 걸린다.
  2. 가비지를 제거하고, 메모리를 반환한다.
    1. 반환되어 비어진 메모리의 참조 위치를 저장해 두었다가, 새로운 객체가 선언되면 이곳에 할당되도록 한다.
  3. 남은 참조되는 객체를 묶는다.
    1. 새로운 메모리 할당 시 더 쉽고 빠르게 할당 진행이 가능하다.

 

3번의 과정을 그림으로 표현

가비지 컬렉션에는 두가지의 GC가 있다.

1. Minor GC

2. Major GC

 

Minor GC

새로 생성된 대부분의 객체는 Eden에 위치한다. 

객체가 계속 생성되어 Eden 영역이 가득 차게되는데, 이때 첫 번째 GC 발생한다.

첫번째 GC가 발생하면 Eden 영역 객체 중 참조되는 것을 Survivor0으로 옮긴 후 이를 제외한 나머지 영역의 객체를 삭제한다.

이후에도 계속 객체를 받다가 Eden과 Survivor 1이 둘다 일정 기준을 넘을 경우 이번에는 Survivor 0의 객체 중 참조되고 있는 객체는 Survivor1로 옮기고, 1을 제외한 나머지 영역의 객체들은 모두 삭제한다.

 

-> 이를 반복해 일정시간 이상 참조되고 있는 객체들은 Old로 옮긴다.

 

간단하게 말하자면...

  1. Eden 영역에 객체가 가득 차게 되면 첫번째 GC가 발생
    1. Eden 영역에 있는 값들을 Survivor 0 영역에 복사하고, 이 영역을 제외한 나머지 영역의 객체를 삭제
  2. Eden 영역과 Survivor 0영역의 메모리가 기준치 이상일 경우 Eden 영역의 객체와 Survivor0 영역에 참조되고 있는 객체가 있는지 검사
    1. 참조되는 객체를 Survivor 1 영역에 복사, 제외한 나머지 영역의 객체를 삭제
  3. 이를 반복해 일정시간 이상 참조되고 있는 객체들을 Old 영역으로 이동

 

Major GC

  1. Old 영역이 꽉 찼을 경우 Old 영역에 있는 모든 객체들을 검사
    1. - 참조되지 않는 객체들을 한꺼번에 삭제
  2. 가비지 객체 삭제
Old Generation은 New/Young Generation보다 크기가 크기 때문에 더 많은 객체가 들어갈 수 있어 GC는 Minor보다 적게 일어나지만, 한번 GC가 발생할 경우 그 시간이 오래 걸린다. 또한, Major GC가 실행되면 프로세스가 정지된다.
이때, 프로세스가 정지 되는 것을 'Stop-the-world'라고 하는데, 보통 GC의 성능 개선을 위해 튜닝을 한다고 하면 'Stop-the-world'의 시간을 줄이는 작업을 말한다.

Major GC가 발생하면 GC를 실행하는 스레드를 제외한 나머지 스레드는 모두 작업을 멈춘다.

 

가비지 컬렉션의 원리

알고리즘에 따라 동작 방식이 다양하지만, 공통적인 원리가 있다.

Garbage Collector는 Heap내의 객체 중 가비지를 찾아내고, 찾아낸 가비지를 처리해 Heap의 메모리를 회수한다. (이러한 행위를 Mark and Sweep 이라 함)

이때, 객체가 가비지인지 아닌지 판단하기 위해 reachability라는 개념을 사용하는데, 어떤 Heap 영역에 할당된 객체가 유효한 참조가 있으면 reachability / 없다면 unreachability로 판단한다.

 

이때 가비지는 참조되고 있지 않은 객체이다. 

 

 

객체가 가비지 컬렉션의 대상이 되었다고 해서 바로 소멸되는 것은 아니다. 

빈번한 가비지 컬렉션의 실행은 시스템에 부담이 될 수 있고, 따라서 성능에 영향을 미치지 않도록 가비지 컬렉션 실행 타이밍은 별도의 알고리즘을 기반으로 계산된다.

728x90

'Computer Science > JAVA' 카테고리의 다른 글

[JAVA] MultiValueMap에 대해  (0) 2022.12.05
[JAVA] JVM 메모리 구조와 가비지 컬렉션 #1  (1) 2022.01.16
복사했습니다!