Gidhub BE Developer

가비지 컬렉션(Garbage Collection) 1편

2018-10-25
goodGid

GC란?

  • GC(Garbage Collection)은 메모리 관리 기법 중의 하나이다.

  • 프로그램이 동적으로 할당했던 메모리 영역 중에서 필요 없게 된 영역을 해제하는 기능이다.


GC 장단점

장점

  • GC를 지원하는 환경에서는

    프로그래머가 동적으로 할당한 메모리 영역의 전체를 완벽하게 관리할 필요가 없어진다.

  • GC는 다음과 같은 버그를 줄이거나 완전히 막을 수 있다.

    • 유효하지 않은 포인터 접근
      • 이미 해제된 메모리접근하는 버그를 가리킨다.
      • 만약 이 포인터가 해제되고 새로운 값이 할당되었다면, 잘못된 값을 읽어오게 된다.
    • 이중 해제
      • 이미 해제된 메모리다시 해제하는 버그를 가리킨다.
      • 일부 메모리 할당 알고리즘에서는 해제된 메모리를 다시 해제하려고 시도하는 오류를 일으킬 수 있다.
    • 메모리 누수
      • 더는 필요하지 않은 메모리가 해제되지 않고 남아있는 버그를 가리킨다.
      • 메모리 누수가 반복되면 메모리 고갈로 프로그램이 중단될 수 있다.
      • 접근 가능한 메모리가 증가하여 메모리가 고갈되는 문제는 GC으로도 막을 수 없다.

단점

  • 어떤 메모리를 해제할지 결정하는 데 비용이 든다.

  • 객체가 필요 없어지는 시점을 프로그래머가 미리 알고 있는 경우에도

    GC 알고리즘이 메모리 해제 시점을 추적해야 하므로 이 작업은 오버헤드가 발생한다.

  • GC가 일어나는 타이밍이나 점유 시간을 예측하기 어렵다.

    즉 할당된 메모리가 해제되는 시점을 알 수 없다.

    그러므로 프로그램이 예측 불가능하게 일시적으로 정지할 수 있다.

    이런 특성은 특히 실시간 시스템에는 적합하지 않다.


JVM 메모리 구조

  • 아래 사진은 자바(JVM)의 메모리 구조이다.

    크게 Heap / Perm / Thread로 나눌 수 있다.

  • Heap은 다시 Young(New) 영역Old 영역으로

    Young 영역은 다시 Eden / Survior1 / Survior2 로 나눌 수 있다.

  • Young 영역은 객체가 처음 생성 시 저장되는 영역을 나타낸다.

    정확하게 말하면 new 연산자를 통해 생성되는 객체들은 EdenSpace에 저장된다.

  • Old 영역은 Young 영역에 존재하던 객체들오래되어 저장되는 영역이다.

  • Perm 영역은 Class 혹은 Method 코드가 저장되는 영역이다.

    하지만 Java 8 이상부터는 Perm 영역이 사라졌다.

    관련해서는 Java 8에서 JVM의 변화 : PermGen이 사라지고 Metaspace가 등장하다. 글을 참고하자.


GC의 종류

  • Java의 GC는 크게 Minor GC와 Full GC로 나눌 수 있다.

  • 그 중 Minor GC는 Young 영역에 발생하는 GC를 나타낸다.

  • GC 종류에 대한 자세한 내용은 가비지 컬렉션(Garbage Collection) 2편에서 알아본다.

Minor GC

  • Young 영역에서 돌아가는 GC라고 생각하면 된다.
  1. 최초 Minor GC가 발생하기 전에

    할당 되어있던 모든 객체는 Eden 영역에만 존재한다.

  2. 이때 Minor GC가 발생하면

    Eden 영역 중 활성 객체가 Survivor1영역으로 이동한다.

    이 후 비활성 객체만 남은 Eden 영역은 Clear 된다.

  3. 다음 Minor GC가 발생하면

    최초 Minor GC 이후 생성된 객체들이 존재하는 Eden 영역의 객체들과

    최초 Minor GC 이후 생존한 객체들이 저장된 Survivor1의 영역 객체들이

    Survivor2로 이동하고

    Eden 영역과 Survivor1영역이 Clear 된다.

  4. 이후 위 작업이 Survivor1과 Survivor2를 번갈아가면서 계속 수행되고

    계속해서 활성 객체로 생존하는 객체들은 시간이 지남에 따라 Old 영역으로 이동한다.

Full GC

  • Old 영역에서 돌아가는 GC라고 생각하면 된다.

  • Full GC는 Old 영역이 Full이 되면 수행된다.

  • Full GC는 Old 영역을 스캔하여 객체들의 참조 상태를 표시하고

    참조되지 않는 객체해제(Mark&Compact)하는 작업을 시행한다.

  • 이러한 Full GC는 속도가 느리고 성능에 아주 큰 영향을 끼친다.

    그 이유는 Full GC가 수행되는 동안 자바 애플리케이션은 멈춤 현상이 발생하기 때문이다.


포인터 추적 방식

  • 대부분의 GC 기법은 포인터 추적 방식을 사용한다.

  • 포인터 추적 방식은

    한 개 이상의 변수접근 가능한 메모리는 앞으로 사용할 수 있는 메모리로 간주하고

    그 밖의 메모리해제하는 방식을 가리킨다.


접근 가능한 객체

  • 접근 가능한 객체는 어떤 변수가 직접 가리키는 메모리 또는 간접적으로 가리키는 메모리를 의미한다.

여러가지 포인터 추적 기법

  • 포인터 추적 기법에는 여러가지 방법이 존재한다.

  • 어떤 언어들은 다음 기법들 가운데 여러가지를 함께 사용하기도 한다.

표시하고 쓸기 (Mark and Sweep)

  • 표시하고 쓸기 기법은 포인터 추적 기법 가운데 가장 단순한 기법이다.

  • 먼저 각 메모리 할당 영역에 표시를 위해 1 비트의 메모리를 남겨 둔다.

    표시 단계에서 모든 변수가 가리키는 영역을 사용 중으로 표시하고

    그 영역에서 가리키는 또 다른 영역 또한 사용 중으로 표시한다.

  • 이처럼 모든 메모리 영역을 표시하고 나면

    표시되지 않은 영역을 접근 불가능한 메모리 영역이 된다.

  • 접근 불가능한 메모리 영역들은 쓸기 단계에서 모두 해제한다.

  • 이 기법의 단점

    표시 단계에서 메모리 내용이 변경되지 않아야 하므로 전체 시스템의 실행이 정지된다는 것이다.

  • 또한 전체 메모리 영역을 검사해야 하므로

    메모리 페이징을 사용하는 운영체제에서 프로그램의 성능이 저하될 수 있다.

삼색 표시 기법

  • 표시하고 쓸기 기법단점을 보완하기 위해 많은 언어삼색 표시 기법을 사용한다.

  • 삼색 표시 기법은 기본적으로 표시하고 쓸기 와 같은 기법이지만

    표시 단계에서 2가지가 아닌 3가지(흰색, 회색, 검은색) 정보 중 하나로 메모리를 표시한다.

  • 이 기법은 다음과 같은 순서로 이루어진다.

  1. 각각의 객체를 흰색, 회색, 검은색으로 분류한다.

    흰색은 더는 접근 불가능한 객체를 가리킨다.

    회색은 접근 가능한 객체이지만 이 객체에서 가리키는 객체들아직 검사되지 않았음을 의미한다.

    검은색은 이 영역에서 가리키는 객체들이 흰색 객체를 가리키지 않음을 의미한다.

  2. GC가 동작 시

    변수가 가리키는 객체들회색으로 표시되며

    그 외의 모든 객체흰색으로 표시된다.

  3. 회색으로 표시된 객체 가운데 하나를 선택하여

    검은색으로 표시하고 이 객체가 가리키는 모든 객체회색으로 표시한다.

  4. 회색 객체가 하나도 남지 않을 때까지 위 과정을 반복한다.

  5. 남은 흰색 객체는 접근 불가능한 객체이므로 모두 해제한다.

  • 이 알고리즘은 표시하고 쓸기 알고리즘 과 달리

    프로그램이 실행 중에도 병행하여 수행할 수 있다.

  • 또한, 메모리가 고갈되었을 때

    GC을 실행하는 것이 아니라 주기적으로 수집하는 것도 가능하다.

객체 이동 기법

  • 객체 이동 기법은 사용 중인 객체다른 영역으로 복사하는 기법을 가리킨다.

  • 객체를 복사하는 것은 언뜻 비효율적으로 여겨질 수도 있으나 다음과 같은 실용적인 장점을 가지고 있다.

    • 해제된 후 재사용 가능한 영역과 사용 중인 영역을 표시하기 위해 추가적인 작업을 할 필요가 없다.

      뇌피셜 :: 새로운 곳에서 공간은 무조건 사용할 수 있기 때문이지 않을까?

    • 따라서 해제된 영역을 포인터로 관리하는 방식에 비해 할당과 해제가 빠르게 이루어진다.

  • 할당된 메모리들이 단편화되는 것을 막을 수 있다.

  • 연결 리스트와 같은 연결형 자료구조에서

    서로 연결된 객체들이 메모리상에서 가까운 위치에 할당될 확률이 높아진다.

    이는 캐시와 관련하여 성능 향상에 도움이 된다.

  • 반면, 메모리 이동 기법은 주기적으로 포인터의 내용이 바뀌므로 포인터 연산을 사용할 수 없게 된다는 단점이 있다.

세대 단위 GC

  • 많은 연구자들은 프로그램에서 새롭게 할당된 영역일수록 금방 해제될 확률이 높다는 관찰을 보고하였다.

  • 세대 단위 GC 기법은 이런 특성을 이용하여

    각각의 객체를 할당된 시간에 따라 세대별로 구분하여

    각 세대별로 서로 다른 메모리 영역에 객체를 할당한다.

  • 만약 한 세대의 메모리 영역이 꽉 차면

    이 메모리 영역에서 살아남은 객체를 더 오래된 메모리 영역으로 옮긴다.

  • 새로 할당된 영역에서는 대부분의 객체가 빠르게 해제되고

    오래된 영역에서는 객체들이 변하지 않을 확률이 높으므로

    이 기법은 메모리의 일부 영역만을 주기적으로 수집하게 되는 장점이 있다.

  • 자바, 닷넷 프레임워크 등 현대적 언어들은 대부분 이 기법을 사용한다.


메모리 관리

  • 메모리 관리는 컴퓨터 메모리를 관리하는 행위이다.

  • 가장 단순한 형태의 메모리 관리 방법은

    프로그램의 요청이 있을 때 메모리의 일부해당 프로그램에 할당하고

    더 이상 필요하지 않을 때 나중에 다시 사용할 수 있도록 해제하는 것이다.

  • 이는 하나 이상의 프로세스가 언제든 실행되는 고급 컴퓨터 시스템에 필수적이다.

  • 가상 메모리 시스템은 프로세스가 사용하는 메모리 주소를 실제 물리 주소구분한다.

    이로써 프로세스를 구분하고

    디스크 스왑 처리를 사용하여 효과적으로 사용할 수 있는 램의 양을 늘릴 수 있게 된다.

  • GC는 프로그램을 위한 컴퓨터 메모리 리소스를 자동으로 할당하고 할당을 해제한다.

  • 프로그래밍 언어 수준에서 일반적으로 추가된 것이며 수동 메모리 관리와 대조된다.


메모리 누수

  • 메모리 누수(memory leak) 현상은 컴퓨터 프로그램이 필요하지 않은 메모리계속 점유하는 현상이다.

  • 할당된 메모리를 사용한 다음 반환하지 않는 것누적되면 메모리가 낭비된다.


Reference


Recommend

Index