포인터 추적 방식
포인터 추적 방식이란 한 개 이상의 변수가 접근 가능한 메모리는 앞으로 사용할 수 있는 메모리로 간주하고 그 밖의 메모리를 해제하는 방식을 의미한다. 대부분의 GC는 포인터 추적 방식을 사용한다.
포인터 추적 방식의 종류
포인터 추적 방식에는 여러 가지 방법이 존재하는데 그 종류를 살펴보자.
표시하고 쓸기(Mark and Sweep)
표시하고 쓸기는 가장 단순한 방식이다. 먼저 각 메모리 할당 영역에 표시를 위해 1 비트의 메모리를 남겨둔다. 표시 단계에서 모든 변수가 가리키는 영역을 사용 중으로 표시하고 그 영역에서 가리키는 영역 또한 사용 중으로 표시한다. 이처럼 모든 메모리 영역을 표시하고 나면 표시되지 않은 영역은 접근 불가능한 메모리 영역이 된다. 접근 불가능한 메모리 영역들은 쓸기 단계에서 모두 해제된다. 표시하고 쓸기의 단점은 표시 단계에서 메모리 내용이 변경되지 않아야 하므로 전체 시스템의 실행이 정지된다는 것이다. 또한 전체 메모리 영역을 검사해야 하므로 메모리 페이징을 사용하는 운영체제에서 프로그램의 성능이 저하될 수 있다.
삼색 표시 기법
삼색 표시 기법은 표시하고 쓸기의 단점을 보완하기 위해 사용한다. 둘은 기본적으로 같은 방식이지만 삼색 표시 기법은 표시 단계에서 3가지 정보(흰색, 회색, 검은색) 중 하나로 메모리를 표시한다. 이 알고리즘은 프로그램이 실행 중에도 병행하여 수행할 수 있다. 또한 메모리가 고갈되었을 때, GC를 실행하는 것이 아니라 주기적으로 수집하는 것도 가능하다. 삼색 표시 기법은 다음과 같은 순서로 이루어진다.
- 각각의 객체를 흰색, 회색, 검은색으로 분류한다.
- 흰색 : 더는 접근 불가능한 객체
- 회색 : 접근 가능한 객체이지만 이 객체에서 가리키는 객체들은 아직 검사되지 않았음을 의미
- 검은색 : 이 영역에서 가리키는 객체들이 흰색 객체를 가리키지 않음을 의미
- GC가 발생하면 변수가 가리키는 객체들이 회색으로 표시되며 그 외의 모든 객체는 흰색으로 표시된다.
- 회색으로 표시된 객체 중 한 개를 선택하여 검은색으로 표시하고 이 객체가 가리키는 모든 객체를 회색으로 표시한다.
- 회색 객체가 하나도 남지 않을 때까지 위 과정을 반복한다.
- 남은 흰색 객체는 접근 불가능한 객체이므로 모두 해제한다.
객체 이동 기법
객체 이동 기법은 사용 중인 객체를 다른 영역으로 복사하는 기법을 가리킨다. 이 방식은 비효율적인 것처럼 느껴지지만 다음과 같은 실용적인 장점을 가지고 있다.
- 해제된 후 재사용 가능한 영역과 사용 중인 영역을 표시하기 위해 추가적인 작업을 할 필요가 없다.
- 따라서 해제된 영역을 포인터로 관리하는 방식에 비해 할당과 해제가 빠르게 이루어진다.
- 할당된 메모리들이 단편화되는 것을 막을 수 있다.
- 연결형 자료구조에서 서로 연결된 객체들이 메모리 상에서 가까운 위치에 할당될 확률이 높아져, 캐시 성능 향상에 도움이 된다.
반면 주기적으로 포인터의 내용이 바뀌므로 포인터 연산을 사용할 수 없게 된다는 단점이 있다.
세대 단위 GC
많은 연구자들은 프로그램에서 새롭게 할당된 영역일수록 금방 해제될 확률이 높다는 관찰을 보고하였다. 세대 단위 GC는 이런 특성을 이용하여 각각의 객체를 할당된 시간에 따라 세대별로 구분하여 각 세대별로 서로 다른 메모리 영역에 객체를 할당한다. 만약 한 세대의 메모리 영역이 꽉 차면 살아남은 객체를 더 오래된 메모리 영역으로 옮긴다. 새로 할당된 영역에서는 대부분의 객체가 빠르게 해제되고 오래된 영역에서는 객체들이 변하지 않을 확률이 높으므로, 이 방식은 메모리의 일부 영역만을 주기적으로 수집하게 되는 장점이 있다. 자바, 닷넷 프레임워크 등 현대적 언어들은 대부분 이 기법을 사용한다.
Reference
'Java' 카테고리의 다른 글
| [Java] Garbage Collection(4) - Young Generational GC, Old Generational GC (0) | 2022.04.14 |
|---|---|
| [Java] Garbage Collection(3) - Generational GC (0) | 2022.04.13 |
| [Java] Garbage Collection(1) - 개요 (0) | 2022.04.11 |
| [Java] Java 8의 특징(7) - 기타 변화들(어노테이션, 병렬 정렬, Metaspace) (0) | 2022.02.28 |
| [Java] Java 8의 특징(6) - CompletableFuture (0) | 2022.02.28 |