티스토리 뷰

JAVA

Garbage Collection

lemonade99 2023. 4. 28. 18:54

목차

GC의 정의

자바 애플리케이션에서 JVM Heap 영역에서 동적으로 할당했던 메모리 영역 중 필요 없게 된 메모리 영역을 자동으로 삭제해 관리해 주는 작업을 의미한다. 위의 작업을 담당하는 것을 가비지 컬렉터라고 하고 해당 작업을 GC라고 한다.

참조되고 있는지에 대한 개념을 reachability라고 하고, 참조되면 reachable, 참조되지 않으면 unreachable라고 한다. GC는 unreachable한 객체들을 garbage라고 인식하게 된다. 

CC++와 같은 언어는 메모리를 할당하고 직접 해제를 해야 하지만,자바에서는 GC를 이용해 개발자들이 메모리 관리 작업에 부담되지 않는다는 장점이 있다. 하지만 GC가 일어나면 GC를 담당하는 쓰레드를 제외한 모든 쓰레드들을 작동을 일시정지하게 되는 단점이 있다. 이것을 Stop The World 현상이라고 부른다.

 

GC의 동작원리 - Mark and Sweep

JVM이 GC를 실행하기 위해 애플리케이션의 실행을 멈추는 작업인 Stop The World를 실행하게 되는데 이후 Mark and Sweep이 실행된다.

 

Mark

가비지 컬렉터에는 GC Root라는 것이 있는데 이것은 힙 외부에서 접근할 수 있는 변수나 오브젝트를 뜻해 말 그대로 가비지 컬렉터의 Root라는 뜻이다. GC Root에서 시작해 이 Root가 참조하는 모든 오브젝트, 또 그 오브젝트들이 참조하는 다른 오브젝트들을 탐색해 내려하며 Mark 한다. 이 단계를 사용되는 메모리와 사용되지 않은 메모리를 식별하는 작업으로 GC의 첫 번째 단계인 Mark 단계이다.

 

Sweep

Mark가 끝나면 가비지컬렉터는 힙 내부를 전체를 돌면서 Mark되지 않은 메모리들을 해제한다. 이 과정을 Sweep이라고 한다.

 

Compact

Sweep 후에 분산된 객체들을 힙의 시작 주소로 모아 메모리가 할당된 부분과 그렇지 않은 부분으로 압축한다. 가비지 컬렉터 종류에 따라 하지 않은 경우도 있다.

 

GC의 동작과정 

Heap 메모리 구조

 

GC는 두가지 조건 하에 만들어졌는데 "대부분의 객체는 금방 접근 불가능 상태가 된다"라는 조건과 "오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다"라는 조건이다. 이러한 조건을 "Weak Generational Hypothesis"라고 한다. 결국 객체는 대부분 일회성이고, 메모리에 오래 남아있는 경우는 적게 존재한다는 것이다. 이 조건의 장점을 살리기 위해 Heap 영역을 Young영역과 Old영역으로 설계하였다.

Young 영역 : 새롭게 생성한 객체의 대부분 여기에 위치하고, 대부분의 객체가 금방 접근 불가능 상태가 되기 때문에 매우 많은 객체가 Young 영역에 생성되었다 사라진다. 이 영역에서 객체가 사라질 때 Minor GC가 발생한다고 말한다.

더 효율적인 GC를 위해 Young 영역을 Eden, survivor 0, survivor 1로 나눈다. 

Eden : new를 통해 새로 생성된 객체가 위치한다. 정기적인 쓰레기를 수집 후 살아남은 객체들은 survivor 영역으로 보내진다.

Survivor 0 / Survivor 1 : 최소 1번의 GC 이상 살아남은 객체가 존재하는 영역으로 Survivor 영역에는 Survivor 0 또는 Survivor 1 둘 중 하나는 꼭 비어 있어야 한다는 규칙이 존재한다.

 

Old 영역 : 접근 불가능 상태로 되지 않아 Young 영역에서 살아남은 객체가 여기로 복사된다. 대부분 Young 영역보다 크게 할당하며, 크기가 큰 만큼 Young 영역보다 GC는 적게 발생한다. Old 영역이 Young영역보다 크게 할당되는 이유는 Young 영역의 수명이 짧은 객체들은 큰 공간을 필요로 하지 않으며 큰 객체들은 Young 영역이 아닌 바로 Old영역에 할당되기 때문이다. 이 영역에서 객체가 사라질 때 Major GC(Full GC)가 발생한다고 말한다.

 

위와 같이 힙 영역을 세부적으로 나눠 GC를 보다 정확하게 불필요한 객체를 제거하는 프로세스를 실행하도록 한다.

 

Minor GC 과정

객체가 새로 생성되면 Young 영역에서 Eden 영역에 할당이 된다. 그리고 Eden 영역이 꽉 차면 Minor GC가 발생하게 되는데, 사용되지 않은 메모리를 해제되고 Eden 영역에 존재하는 객체는 사용중인 Survivor 영역(Survivor 규칙에 의해 반드시 1개의 영역에만 데이터가 존재)으로 옮겨지게 된다. 이러한 과정이 반복해 계속해서 살아남은 객체는 Old 영역으로 이동된다.

Minor GC의 동작

인스턴스가 계속 생성되어 Eden 영역이 포화되어 Stop the world가 실행되고 Mark and Sweep이 실행된다. 여기서 살아남은 객체가 첫 Survivor 영역으로 이동하고 해당 Survivor 영역이 포화되면 Mark and Sweep으로 살아남은 객체가 두 번째 Survivor 영역으로 이동을 한다. 일정 횟수(age) 이상 살아남은 객체를 Old 영역으로 이동한다. 

Survivor 영역에서 객체가 살아남은 횟수를 age라고 하며, age를 Object Header에 기록한다.

 

Major GC 과정

Young 영역에서 오래 살아남은 객체는 Old 영역으로 이동되는데 Major GC는 객체들이 계속 이동되어 Old 영역의 메모리가 부족해지면 발생하게 된다. 크기가 작은 Young 영역에서의 Minor GC에 비해 Major GC는 10배 이상의 시간이 소모될 수 있다.

 

Reference

https://whitepro.tistory.com/462

https://mangkyu.tistory.com/118

'JAVA' 카테고리의 다른 글

ElasticSearch와 연동후 인덱스 설정하기  (0) 2023.08.07
Redis를 이용한 랭킹 동점 처리 구현  (0) 2023.06.23
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함