Generation은 객체가 Garbage Collection을 몇번 거쳤는지 나타낸다
세대가 높을 수록 즉, Garbage Collection을 겪고도 생존한 객체들을 중요한 객체로 판단하는 방식
기본적으로 0세대를 대상으로 먼저 Garbage Collection을 시행하고, 그럼에도 공간확보가 부족하다면 1세대까지 포함, 그럼에도 부족하다면 2세대까지 포함시켜 시행한다
📢 2세대까지 포함한 모든 Garbage Collection 수행 시 아예 프로세스를 일시정지하고 우선적으로 수행하기 때문에, 순간적인 프레임 드랍 등이 일어나게 됩니다.
Garbage Collection 주기가 시작될 때 일단 모든 object를 가비지로 가정한다.
즉, 루트 목록 내 어떤 루트도 메모리를 가리키고 있지 않다고 가정한다.
이 상태에서 가비지 컬렉터는 루트 목록을 돌면서 각 루트가 참조하는 것들을 마킹한다.
루트가 참조하는 힙 object가 또 다른 힙 object를 참조한다면 이 object 또한 마킹한다.
좀 더 언밀히 말하면 마킹이란 루트 목록에서 시작되는 연결된 그래프를 만드는 것이다.
루트에서 연결될 수 있는 object를 우리는 도달할 수 있는 object라 부른다.
루트 목록에서 도달할 수 없는 object들을 가비지로 간주한다.
가비지가 차지한 공간은 비어 있는 공간으로 간주하게 된다.
루트 목록에 대한 조사가 끝나면 가비지 컬렉터는 힙을 순회하며 가비지가 차지했던 비어있는 공간에 인접한 도달할 수 있는 object들을 메모리 복사를 통해 덮어 씌운다.
도달 가능한 모든 object에 대한 이동이 끝나면 가비지 컬렉터는 포인터의 위치 또한 적절하게 수정한다
- 객체 너무 많이 할당하지 않기
너무 많은 object를 생성하면 그 만큼 메모리가 금방 차고 Garbage Collection이 빈번히 발생하게 될 것이다.
- 너무 큰 객체 할당하지 않기
- 복잡한 참조 관계 만들지 않기
Garbage Collection 후 도달할 수 있는 object의 세대를 옮기기 위해 메모리 복사를 수행한다. 이때 참조 관계가 복잡하다면 단순히 메모리 복사가 아니라 참조하고 있는 모든 메모리 주소를 수정하는 과정을 거쳐야 한다.
- 루트를 많이 만들지 않기
루트 목록을 기반으로 가비지를 찾아내기 때문에 많지 않다면 그만큼 루트 목록을 순회하는 시간을 줄일 수 있다.