TIL

GC

Garbage Collector란

프로그램이 실행되다 보면 더 이상 아무도 사용하지 않는 객체가 Heap 영역에 남아 있게 된다. 이 유효하지 않은 메모리가 계속 남아 있게 된다면 언젠가 Heap 영역은 가득 차서 더 이상 프로그램을 진행할 수 있는 메모리가 남지 않을 것이다.

JVM 실행 엔진 내부에 있는 Garbage Collector는 불필요한 메모리(garbage)를 자동으로 정리해 주는 기능을 한다.

Garbage Collector는 개발자가 따로 신경 쓰지 않아도 heap 메모리를 살펴 보고 사용 중인 객체와 사용하지 않는 객체를 식별하고 사용하지 않는 객체를 삭제한다.

사용되지 않는 객체 = 참조되지 않는 객체

GC 기본 프로세스

  1. Marking

Garbage Collector가 사용 중인 메모리와 사용하지 않는 메모리를 식별한다.

  1. Normal Deletion

참조되지 않는 객체를 메모리에서 삭제하고, Memory allocator가 메모리에서 삭제된 여유 공간에 대한 포인터를 가지고 있는다. (새로운 메모리 할당이 요구될 때를 대비해서)

2a. Deletion with Compacting

성능을 향상 시키기 위해 참조되지 않는 객체를 삭제한 뒤 남은 참조된 객체들을 압축한다. 이렇게 하면 새로운 메모리 할당이 더 간단하고 빨라진다.

JVM Generations

하지만 모든 참조 되지 않는 메모리를 식별하고 참조된 객체를 압축하는 등의 작업은 비효율적이다. 객체가 더 많이 할당될 수록 GC를 하는 시간은 더 늘어나지만 대부분의 객체의 수명은 짧다. (메모리에 오래 남아 있지 않는다.)

때문에 객체 생존 기간에 따라 물리적으로 Heap 영역을 나누게 되었다. img.png

GC 동작 방식

Mark and Sweep

Stop the World

동작 과정

  1. Young 영역의 eden 공간에 새객체가 할당된다. (처음엔 두 survivor 공간(S0, S1)은 비어있다.)
  2. eden 공간이 가득 차면 minor GC가 발생한다.
  3. 참조가 남아있는 객체는 첫 번째 survivor 영역인 S0으로 이동하고, 참조 되지 않는 객체는 삭제된다.
  4. 다음 minor GC가 일어날 때 3번과 같은 동작이 벌어진다.
    1. 하지만 3번과 다른 점은 두 번째 survivor 공간인 S2로 참조 객체들이 이동한다.
    2. 그리고 이전 minor GC에서 S0으로 이동 되었던 객체들이 살아 남았다면 threshold가 상승하고 S1로 이동한다.
    3. 모든 참조 객체가 S1간으로 이동하면 S0을 비워지고 S1에는 threshold가 다른 객체들이 함께 존재하게 된다.
  5. 다음 minor GC가 발생하면 4번과 똑같이 동작하며 S1 비워지고 S0이 채워진다.
    1. 살아남은 객체들은 threshold가 증가한다.
  6. 위와 같은 동작이 반복되고 몇몇 객체들의 threshold가 임계치를 넘어가면 old generation으로 이동한다.
  7. minor GC가 계속되고 old generation 영역이 채워지는데 old 영역이 가득차면 major GC가 발생한다.

https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

https://mangkyu.tistory.com/118

https://d2.naver.com/helloworld/1329

https://www.youtube.com/watch?v=FMUpVA0Vvjw