[CS]GC : Garbage Collection

김피자·2023년 1월 27일
0

CS

목록 보기
6/22

Garbage Collection : 가비지 컬렉션

: 자바의 메모리 관리방법 중 하나로 JVM의 Heap 영역에서 동적으로 할당했던 메모리 영역 중 필요없게 된 메모리 영역을 주기적으로 삭제하는 프로세스

C나 C++에서는 가비지 컬렉션 없이 프로그래머가 수동으로 메모리 할당과 해제를 하나하나 해줘야하지만 Java는 JVM에 탑재되어 있는 가비지 컬렉터가 메모리 관리를 대행해주기 때문에 메모리 관리, 메모리 누수 문제에 대해 완벽하게 관리하지 않아도 개발에만 집중할 수 있다는 장점이 있음


stop-the-world

: CG를 실행하기 위해 JVM 애플리케이션 실행을 멈추는 것

stop-the-world가 발생하면 CG를 실행하는 스레드를 제외한 나머지 모든 스레드가 작업을 멈춤 > CG작업이 완료되면, 중단됐던 작업이 재개

어떤 알고리즘을 사용하더라도 stop-the-world가 발생하기 때문에, CG성능 최적화는 결국 이 stop-the-world타임을 줄이는 것을 의미


JVM의 메모리는 Class Stack Heap Native Method PC 총 5가지로 이루어져 있는데, GC는 이 중 Heap을 관장함

GC의 대상


: 객체들은 실질적으로 Heap영역에서 생성되고 Method Area나 Stack Area 등은 Heap에서 생성된 객체의 주소만 참조하는 형식으로 구성됨
하지만, 이렇게 생성된 Heap의 객체들이 메소드가 끝나는 등의 특정 이벤트들로 인하여 Heap 객체의 메모리 주소를 가지고 있는 참조 변수가 삭제되는 현상이 발생하면 그림처럼 빨간색 객체와 같이 Heap영역 어디서든 참조하고 있지 않은 객체가 발생하게 됨
이 객체들을 Unreachable하다고 하여 주기적으로 가비지 컬렉터가 제거함

Reachable : 객체가 참조되고 있는 상태
Unreachable : 객체가 참조되고 있지 않은 상태 (GC의 대상)
  • Unreachable한 객체
  • 값이 Null인 객체
  • 특정 블럭 실행 종료 시 블럭 내에서 생성된 객체
  • 부모 객체가 Null일 때, 해당 객체가 포함하고 있는 자식 객체

본격 들어가기 전, 짧게 GC의 알고리즘을 살펴보자

  1. GC-Root로 부터 참조되는 객체와 그 Reachable 객체가 참조하는 객체를 찾아서 Marking
  2. Marking 과정이 끝나면 Unreachable 객체를 메모리에서 해제(Sweep)
  3. 살아남은 영역을 조각모음(Compact)하는 Mark and Sweep Compact 알고리즘을 기본으로 사용

GC 메모리 해체 과정

1. Marking

메모리가 사용되는지 안되는지를 구분함
위 사진은 참조되고 있는 객체는 파란색, 참조되고 있지 않은 객체는 주황색으로 마킹했음

모든 객체를 하나씩 스캔하여 마킹하기 때문에 오랜 시간을 소모함

2. Normal Deletion

이전 단계에서 참조되고 있지 않다고 마킹한 객체를 제거하고 메모리를 반환

Memory Allocator은 반환되어 빈 곳의 주소를 저장해뒀다가 새로운 객체가 선언되면 이 곳에 할당하도록 함

하지만!! 이렇게 하면 메모리가 단편화되어 비효율적으로 사용됨
그래서 이 흩어진 객체들의 영역을 한 곳으로 모으는 과정이 필요함

단편화 : 기억 장치의 빈 공간 또는 자료가 여러 개의 조각으로 나뉘는 현상
이 현상은 기억장치의 사용 가능한 공간을 줄이거나, 읽기와 쓰기의 수행속도를 늦추는 문제점을 일으킴

3. Compacting

메모리의 단편화를 최소화하기 위해 참조되는 객체들을 한 곳으로 집약시켜 남은 공간을 극대화 > 새로운 메모리 할당 시 더 쉽고 빠르게 진행 가능

위 까지의 과정을 Mark & Compact라고 함
하지만 위 처럼 JVM에서 모든 객체를 탐색하며 일일히 참조되고 있는지 안되고 있는지 마킹하고 메모리 해제하고 또 다시 압축하고 완전 복잡함 복잡하면 뭐다? 비효율적이다~

Week Generational Hypothesis(약한 세대 가설)

GC는 에이징과 함꼐 세대별 청소를 사용해 힙 영역의 공간을 최대한 확보

root set으로부터 접근 불가능한 모든 객체들은 쓰레기로 간주돼 GC에 의해 수집되는데 GC가 수행될 때마다 하나하나 추적하는 것은 부하가 큰 일

하지만!! 아래 그래프처럼 대부분의 응용프로그램에서 객체들이 짧은 시간동안만 살아 있다는 것을 확인
이를 약한 세대 가설이라고 함

위 그래프는 대부분의 응용 프로그램들의 object 수명을 나타낸 그래프

  • x축 : 측정된 객체의 lifetime 즉, 수명
  • y축 : lifetime이 있는 객체의 총 byte

이 결과를 통해 대부분의 객체들은 생성된지 얼마 안 가 소멸한다는 것을 알 수 있음

  • 대부분 객체는 금방 접근 불가능 상태(Unreachable)가 된다
  • 오래된 객체에서 생성된지 별로 안 된 객체로의 참조는 아주 적게 존재한다

신규로 생성한 객체의 대부분은 머지않아 사용하지 않는 상태가 되고, 오래된 객체에서 신규 객체로의 참조는 매우 적게 일어난다는 가정이 바로 Week Generational Hypothesis

Generational Gabage Collection

이러한 가설 아래 Young영역과 Old영역으로 메모리를 분할해 새롭게 생성되는 객체는 Young영역에 보관하고, 생성된지 시간이 지난 그러니깐 점차 나이를 먹은 객체는 Old영역에 보관하는 알고리즘이 고안됨
약한 세대 가설을 최적화하기 위해 Java의 메모리는 아래처럼 세대 단위로 관리

어떤 세대의 메모리 풀이 가득 찬다면 해당 세대에서만! GC가 실행

GC가 수행된 후 남은 객체들은 메모리의 오른쪽(Old Generation)으로 이동
이것을 promoted 또는 tenured라고 함

young Generation은 빨리 모이기 때문에 여기에 관한 GC는 속도를 중시함
반번, Old Generation 관련 알고리즘들은 공간 효율을 중시함
~~왜냐하면 대부분 Old Generation은 힙의 대다수 부분을 차지하니깐

Young Generation

새롭게 생성한 객체들의 대부분은 여기에 자리잡음
약한 세대 가설(Week Generational Hypothesis)에 따르면, 대부분 객체가 금방 접근 불가능한 상태(Unreachable)가 되기 때문에 매우 많은 객체가 이 영역에서 생성됐다가 사라졌다가 함

해당 영역에서 객체가 메모리 해제되는 경우를 Minor GC가 발생했다고 말함

Old Generation

금방 접근불가 상태가 된 애들과 달리 오랫동안 메모리에 남아있던 객체들이 이 영역으로 복사됨
대부분 Young영역보다 크게 할당하며 크기가 큰 만큼 GC는 Young영역에 비해 적게 발생

해당 영역에서 객체가 메모리 해제되는 경우를 Major GC가 발생했다고 말함

Permanent

Method Area라고도 부르는 이 영역은 JVM이 클래스들과 메소드들을 설명하기 위해 필요한 다양한 메타 데이터들을 포함하고 있음
JDK8 부터는 Metaspace로 교체


Generational Gabage Collection 과정

1. 새로운 객체가 생성되면 Young영역의 Eden Space에 할


Eden 최초 생성된 객체를 위한 공간

2. Eden Space가 가득차면 Minor GC수

3. 참조되는 객체들은 S0(1번째 생존 영역)으로 이동하고, 참조되고 있지 않은 객체는 Eden Space가 클리어 될 때 같이 반환 (바이바이~)

4. 다음번 Minor GC 때, Eden Space에서 똑같은 일 발생

비 참조 객체는 사라지고, 참조 객체는 마찬가지로 Survivor영역으로 이동
하지만 이번에는 두 번째 영역인 S1영역으로 이동함

또한, 최근 Minor GC에서 S0영역으로 이동된 객체들도 Age가 증가하고,
S1영역으로 이동

모든 객체들이 S1영역으로 이동하게되면 Eden Space와 S0영역 모두 클리어

5. 다음 Minor GC때 또 같은 작업 반복

하지만 이번 과정에서는 Survivor 영역이 서로 스위치!
참조되는 객체들은 S0로 이동하고, 살아남은 객체들은 Age가 증가함
그리고 Eden Space와 S1영역은 클리어!

6. Minor GC이후 일정한 Age 한계치를 넘은 객체들이 Old Generation으로 프로모션 됨

(아래 그림의 Age Threshold : 8살)

7. Minor GC가 계속될수록 틀 객체들이 Old Generation영역으로 이

위 과정 한눈에 보자면

  1. Eden 영역에 최초로 객체 생성
  2. Survivor 영역을 통해 오래 살아남은 객체가 Old 영역으로 이동

Minor GC가 발생하면서 살아남은 객체는 Aging되고, 일정 Age threshold 값을 넘게되면 Old영역으로 할당된다는 것을 기억하기


요약

GC의 메모리 해제 과정에는 Marking, Deleting, Compacting 이렇게 크게 3가지가 있으며, 좀 더 효율적으로 하기 위해 Heap영역을 Young, Old, Permanent로 나눔

중요한 것은
GC가 수행될 때 일시적으로 애플리케이션 수행이 정지되며, Stop-the-World의 시간을 줄이는게 핵심


참고
https://docs.oracle.com/en/java/javase/16/gctuning/garbage-collector-implementation.html#GUID-71D796B3-CBAB-4D80-B5C3-2620E45F6E5D
https://velog.io/@haero_kim/Garbage-Collection-%EA%B8%B0%EC%B4%88-%EA%B3%B5%EB%9E%B5%ED%95%98%EA%B8%B0
https://brorica.tistory.com/m/entry/%EC%9E%90%EB%B0%94-gc
https://reference-m1.tistory.com/107
https://learn.microsoft.com/ko-kr/dotnet/standard/garbage-collection/performance

profile
제로부터시작하는코딩생활

0개의 댓글