본문 바로가기

Java

Java GC 처리방법

  • GC랑 garbage collection으로 메모리 관리 기법 중 하나이다
  • 프로그램이 동적으로 할당한 메모리 영역 중 필요없게 된 영역을 해제하는 기능이다
    • 포인터 추적 방식은 한개 이상의 변수가 접근 가능한 메모리는 앞으로 사용할 수 있는 메모리로 간주하고 그 밖의 메모리를 해제하는 방식을 가리킨다
    • GC를 하는 방식으로는 포인터 추적 방식을 대부분 사용한다
      • 접근 가능한 객체는 어떤 변수가 집접 가리키는 메모리 또는 간접적으로 가리키는 메모리를 의미
      • 포인터 추적 방식
        • 가장 단순한 기법
        • 영역 표시를 위해 각 메모리 할당 시 1비트의 메모리를 남겨둔다
        • 표시단계에서 모든 변수가 가리키는 영역을 사용 중으로 표시하고 그 영역에 서 가리키는 또다른 영역 또한 사용중으로 표시
        • 접근이 불가능한 메모리 영역들은 쓸기 단계에서 모두 해제한다
        • 단점은, 표시 단계에서 메모리 내용이 변경되지 않아야 하기 때무에 전체 시스템의 실행이 정지된다는 것이다
        • 또한 전체 메모리 영역을 검사해야 하므로 메모리 페이징을 사용하는 운영체제에서 프로그램의 성능이 저하될 수 있다
        [2]삼색 표시 기법
        • 표시하고 쓸기 기법의 단점을 보완하기 위해 많은 언어들은 삼색 표시 기법을 사용한다
        • 표시하고 쓸기 기법과 같은 기법이지만 표시단계에서 2가지가 아닌 3가지(흰색, 회색, 검은색) 정보 중 하나로 메모리를 표시
        • 회색으로 표시된 객체 가운데 하나를 선택하여 검은색으로 표시하고, 이 객체가 가리키는 모든 객체를 회색으로 표시한다
        • 회색 객체가 하나도 남지 않을 때까지 위 과정 반복
        • 남은 흰색 객체는 접근이 불가능한 객체이므로 모두 해제한다
          • 프로그램 실행 중에도 병행하여 수행 할 수 있다
          • 메모리가 고갈되었을 때 쓰레기 수집을 실행하는 것이 아니라 주기적으로 수집하는 것도 가능하다
        [3]객체 이동 기법
        • 객체 이동 기법은 해제되지 않은 객체를 그대로 두는 것이 아니라 다른 영역으로 복사하는 기법
        • 원래대로 유지해도 되는 객체를 복사하는 것은 비효율적으로 보일 수 있다
        • 하지만 실용적 장점 또한 있다
          • 해제된 후 재사용 가능한 영역과 사용 중인 영역을 표시하기 위해 추가적인 작업을 할 필요가 없다
          • 해제된 영역을 포인터로 관리하는 방식에 비해 할당과 해제가 빠르게 이루어진다
        • 할당된 메모리들이 단편화되는 것을 막을 수 있다
        • 연결리스트와 같은 연결형 자료구조에서 서로 연결된 객체들이 메모리 상에서 가까운 위치에 할당될 확률이 높아진다
        • 이는 캐시와 관련하여 성능 향상에 도움이 된다
        • 메모리 이동기법은 주기적으로 포인터의 내용이 바뀌므로 포인터 연산을 사용할 수 없게 된다는 단점
        [4]세대 단위 쓰레기 수집
        • 많은 연구자들을 프로그램에서 새롭게 할당된 영역일수록 금방 해제될 확률이 높다는 관찰을 보고하였다
        • 각각의 객체를 할당된 시간에 따라 세대별로 구분하여 각 세대별로 서로 다른 메모리 영역에 객체를 할당한다
        • 만약 한 세대의 메모리 영역이 꽉 차면 이 메모리 영역에서 살아남은 객체를 더 오래된 메모리 영역으로 옮긴다
        • 새로 할당된 영역에서는 대부분의 객체들이 빠르게 해제되고 오래된 영역에서는 객체들이 변하지 않을 확률이 높으므로 이 기법은 메모리의 일부 영역만을 주기적으로 수집하게 되는 장점이 있다
        • 자바, 닷넷 프레임우커ㅡ 등 현대적 언어들은 대부분 이 기법을 사용한다
      • [1]표시하고 쓸기(mark and sweep)

[추가적으로 알아두면 좋은 점]

  • 장점 : 개발자가 동적으로 할당한 메모리 영역의 전체를 완벽하게 관리할 필요가 없어진다
    • 아래와 같은 버그를 줄여준다
    [1]유효하지 않은 포인터 접근
    • 이미 해제된 메모리에 접근하는 버그를 가리킨다
    • 만약 이 포인터가 해제되고 새로운 값이 할당되었다면, 잘 못된 값을 읽어오게 된다
    [2]이중해제
    • 이미 해제된 메모리를 다시 해제하는 버그
    • 일부 메모리 할당 알고리즘에서는 해제된 메모리를 다시 해제하려고 시도하는 오류를 일으킬 수 있다
    [3]메모리 누수
    • 더 이상 필요하지 않은 메모리가 해제되지 않고 남아있는 버그
    • 메모리 누수가 반복되면 메모리 고갈로 프로그램이 중단될 수 있다
    • 접근 가능한 메모리가 증가하여 메모리가 고갈되는 문제는 쓰레기 수집으로도 막을 수 없다
  • 단점[2]객체가 필요 없어지는 시점을 프로그래머가 미리 알고 있는 경우에도 GC알고리즘이 메모리 해제 시점을 추적해야 하므로 이 작업은 오버헤드가 발생한다따라서, 예측불가능하게 일시적으로 프로그램이 정지할 수 있다
  • [4]위 단점들로 인해 실시간 시스템에는 적합하지 않다
  • [3]쓰레기 수집이 일어나는 타이밍이나 점유시간을 미리 예측하기 어렵다 → 할당된 메모리가 해제되는 시점을 알 수가 없다
  • [1]어떤 메모리를 해제할지 결정하는데 비용이 든다
  • 종류에는 크게 Minor GC와 Full GC 2가지가 있다