GC(Garbage Collection)란? + GC 기법에 대해

wannabeking·2022년 7월 6일
0

CS

목록 보기
7/27

GC(Garbage Collection)란?

  • 메모리 관리 기법 중 하나로 프로그램이 동적으로 할당했던 메모리 영역 중에서 필요없게 된 영역을 해제하는 기능이다.
  • 더 이상 필요없게 된 영역이란 어떤 변수도 가리키지 않게 된 영역을 의미한다.
  • Java의 경우 처음부터 GC 기법을 염두에 두고 설계되어 언어 정의에 쓰레기 수집이 포함되어 있다.
  • 다음과 같은 버그들을 줄이거나 완전히 막을 수 있다는 장점을 가진다.
    • 유효하지 않은 포인터 접근 방지
      • 이미 해제된 메모리에 접근하는 버그로 만약 이 포인터가 해제되고 새로운 값이 할당되었다면 잘못된 값을 읽어온다.
    • 이중 해제
      • 이미 해제된 메모리를 또다시 해제하는 것이다.
    • 메모리 누수
      • 더이상 필요하지 않은 메모리가 해제되지 않고 남아있으면 메모리 고갈로 프로그램이 중단될 수 있다.
  • 반면에 다음과 같은 단점들도 존재한다.
    • 어떤 메모리를 해제할지 결정하는 비용이 들어 오버헤드가 된다.
    • GC가 일어나는 타이밍이나 점유 시간을 예측하기 어렵다.
    • 할당된 메모리가 해제되는 시점을 알 수 없다.


대부분의 GC 기법인 포인터 추적 방식

  • 한 개 이상의 변수가 접근 가능한 메모리는 앞으로 사용할 수 있는 메모리로 간주하고, 그 밖의 메모리를 해제하는 방식이다.
  • 포인터 추적 방식을 사용하는 여러가지 기법이 존재한다.
    • 표시하고 쓸기
      • 가장 단순한 기법이다.
      • 각 메모리 할당 영역을 표시하기 위해 1비트의 메모리를 남겨 둔다.
      • 표시 단계에서 모든 변수가 가리키는 영역을 "사용 중"으로 표시하고, 그 영역에서 가리키는 또다른 영역 또한 "사용 중"으로 표시한다.
      • 표시되지 않은 영역을 접근 불가능한 메모리 영역으로 간주하고 쓸기 단계에서 모두 해제한다.
      • 표시 단계에서 메모리 내용이 변경되지 않아야 하기 때문에 전체 시스템의 실행이 정지되는 단점이 존재한다.
      • 또한 전체 메모리 영역을 검사해야 하므로 메모리 페이징을 사용하는 운영체제에서 프로그램의 성능이 저하될 수 있다.
    • 삼색 표시 기법
      • 표시하고 쓸기와 같은 기법이지만, 표시 단계에서 2가지가 아닌 3가지(흰색, 회색, 검은색)정보 중 하나로 메모리를 표시한다.
      • 흰색은 더 이상 접근 불가능한 객체, 회색은 접근 가능한 객체이지만 이 객체에서 가리키는 객체들은 아직 검사되지 않음, 검은색은 이 영역에서 가리키는 객체들이 흰색 객체를 가리키지 않음을 의미한다.
      • 순서는 다음과 같다.
        1. 각각의 객체를 흰색, 회색, 검은색으로 분류한다.
        2. 회색으로 표시된 객체 가운데 하나를 선택하여 검은색으로 표시하고 이 객체가 가리키는 모든 객체를 회색으로 표시한다.
        3. 회색 객체가 하나도 남지 않을 때까지 위 과정을 반복한다.
        4. 남은 흰색 객체는 접근 불가능한 객체이므로 모두 해제한다.
      • 프로그램이 실행 중에도 병행하여 수행할 수 있으며 메모리가 고갈되었을 때 쓰레기 수집을 실행하는 것이 아닌, 주기적으로 수집하는 것도 가능하다.
    • 객체 이동 기법
      • 해제할 객체 표시가 완료된 후 해제되지 않은 객체를 그대로 두는 것이 아닌 다른 영역으로 복사하는 기법이다.
      • 다음과 같은 장점을 가지고 있다.
        • 해제된 후 재사용 가능한 영역과 사용 중인 영역을 표시하기 위해 추가적인 작업을 할 필요가 없다.
        • 할당된 메모리들이 단편화되는 것을 막을 수 있다.
        • 서로 연결된 객체들이 메모리 상에서 가까운 위치에 할당될 확률이 높으므로 캐시와 관련하여 성능이 향상된다.
      • 하지만 주기적으로 포인터의 내용이 바뀌므로 포인터 연산을 사용할 수 없는 단점이 있다.
    • 세대 단위 쓰레기 수집
      • 새롭게 할당된 영역일수록 금방 해제될 확률이 높다는 특성을 이용하였다.
      • 각각의 객체를 할당된 시간에 따라 세대별로 구분하여, 각 세대별로 서로 다른 메모리 영역에 객체를 할당한다.
      • 만약 한 세대의 메모리 영역이 꽉 차면, 이 메모리 영역에서 살아남은 객체들을 더 오래된 메모리 영역으로 옮긴다.
      • Java가 이 기법을 사용한다.


참조 횟수 계산 방식

  • 일부 GC 기법은 참조 횟수 계산 방식을 사용한다.
  • 다음과 같은 장점을 가지고 있다.
    • 객체가 접근 불가능해지는 즉시 메모리가 해제되므로 객체의 해제 시점을 어느정도 예측할 수 있다.
    • 객체가 사용된 직후에 메모리를 해제하므로 이미 캐시에 저장되어 있는 객체를 빠르게 메모리에서 해제할 수 있다.
  • 반면, 다음과 같은 단점들이 존재한다.
    • 두 개 이상의 객체가 서로를 가리키고 있을 경우에 참조 횟수가 0이 되지 않기 때문에 메모리 누수가 발생한다. 참조 횟수를 증가시키지 않는 약한 참조를 사용하게 해결할 수 있다.
    • 멀티 스레드 환경에서 스레드 간에 공유하는 객체의 참조 횟수를 계산하려면 락을 걸어야할 수 있다. 이 문제를 피하기 위해 스레드 단위 지역변수로 참조 횟수를 따로 관리하면서 스레드 단위에서 참조 횟수가 0이 될 때 전역 참조 횟루를 확인하는 방식을 사용할 수 있다.
    • 참조 횟수가 0이 될 때 해당 객체가 가리키는 다른 객체들 또한 동시에 0으로 만드는 작업이 일어나는데, 이 과정에서 많은 시간이 걸릴 수 있어 실시간 시스템에는 적합하지 않을 수 있다.


profile
내일은 개발왕 😎

0개의 댓글