GC (Garbage Collection)
GC는 Java나 C#에서 메모리를 자동으로 해제해주는 기능이다.
C/C++에서는 자주 사용하는 힙영역에 대한 메모리 해제 때문에 Memory leak가 쉽게 일어난다. -> 메모리 조각 발생
C/C++에서는 C-runtime을 사용하여 힙에 객체를 할당하여 자유 메모리 블록을 찾고 쪼개고 재조정하는 탐색, 분할의 과정을 거치는데 C#에서는 Garbage Collector가 사용하지 않는 객체를 알아서 판단하여 메모리를 회수한다.
.Net 프레임워크에서 참조 형식의 객체가 할당될 때는 Stack 영역에는 Heap의 메모리 주소(Object를 가리키는 참조값)를, Heap 영역에 실제 값(Object 값)이 할당된다. 그리고 객체가 할당된 코드블록이 끝나면 Stack 영역의 메모리가 회수되고 Heap 영역의 값이 쓰레기가 된다. 여기서 회수된 Stack의 객체를 Root라고 한다.
.Net 프레임워크에서는 프로그램이 실행되면 JIT 컴파일러가 Root들을 목록으로 만들고 CLR이 Root 목록을 관리하며 상태를 갱신하게 된다.
Garbage Collector는 Heap 영역이 다 차게 되면 모든 객체가 쓰레기라고 가정한 뒤 Root 목록을 순회하며 Heap 객체와의 관계 여부를 조사한다. -> 어떤 Root와도 관계가 없는 Heap의 객체들은 쓰레기로 간주된다.
이후 쓰레기가 차지하고 있던 메모리가 회수되면 인접 객체들을 이동시켜 차곡차곡 채워서 정리한다.
이러한 방법은 Heap 전체를 검사할 필요가 없어 C/C++ 보다 빠른 성능을 가진다.
CLR은 메모리를 효율적으로 관리하기 위해 0~2세대로 나누는데
0세대 : GC가 아직 적용되지 않는 객체
1세대 : 0세대와 2세대 사이
2세대 : GC를 2번 이상하고도 Heap에 저장되어 있는 객체
GC가 실행되면 0 -> 1 -> 2 순으로 세대로 교체되거나 사라진다.
GC의 단점
1. 사용자가 메모리가 언제 해제되는지 정확하게 알 수 없다.
2. GC가 동작하는 동안에는 다른 동작을 멈추기 때문에 *오버헤드가 발생한다.
*오버헤드 : 프로그램의 실행도중 동떨어진 위치의 코드를 실행시킬 때 추가적으로 시간, 메모리, 자원이 사용되는 현상