기술 면접 시 제대로 대답하지 못한 내용을 공부하며 정리한다.
Java의 메모리 구조와 GC에 대해 자세히 공부한다.
컴퓨터 구조시간에 배운 메모리 구조는
이렇게 구성되어 있다.
Java의 경우 JVM 상에서 실행이 되는데 이로 인해 JVM 내의 메모리 구조가 존재한다.


Class Loader가 바이트 코드 로딩Execution Engine은 바이트 코드를 하나씩 실행Java와 같은 Managed 언어의 경우 가비지 컬렉션(GC)가 존재하여 메모리를 자동으로 관리해준다.
가비지 컬렉션은 어떤 Object를 Garbage로 판단해서 지울까?
바로 Reachable 여부이다. 다른 말로 말하면, Reference(참조)를 체크한다.

다른 영역에서 해당 객체를 참조하고 있다면 Reachable, 참조하고 있지 않다면 Unreachable로 판단한다.
참조하고 있지 않은 Object는 GC의 대상, 즉 Gabage로 인식한다.
GC가 수행되는 방식이다.
Root Space부터 그래프 순회를 통해 연결된 객체를 찾아내어 어떤 객체를 참조하고 있는지 마킹
Java의 Heap 영역의 경우, 크게 Young 영역과 Old 영역으로 나뉜다.
객체가 처음 생성되면 Young 영역의 Eden 부분에 배정되고, '특정 조건'이 되면, Old 영역으로 배정된다.(추후 기술)

Young 영역에서 발생하는 GC 를 Minor GC 라고 한다.
1. 객체 생성시 Eden 영역에 배정
2. Eden 꽉차면, Minor GC 실행
3. 살아 남은 객체들은 한쪽 Survivor 영역으로 이동
4. 다시 Eden 꽉차면, Survivor영역을 포함해서 GC 실행
5. 여기서 살아남은 객체들을 반대쪽 Survivor 영역에 저장
6. 4 ~ 5 반복
포인트는 한쪽 Survivor 영역은 항상 비어 있다는 것이다.
Old 영역에 배정된다.객체의 특징 때문이다. 객체들은 대부분 빠른시간 내에 생성되었다가 소멸되며, 일부 객체만 아주 오랜시간 살아남는다.
Old영역에 들어갔다는 말은 오랫동안 GC를 실행시키지 않겠다는 의미이며, Minor GC에서는 Old 영역을 대상에서 제외하여 성능을 높인다.
이는 기존 old, young 영역 방식을 유지하면서도 STW를 줄이기 위해 노력했다.
이러한 방법을 통해 어플리케이션 쓰레드가 정지하는 시간을 최소화 했다.
여기서 가장 큰 변화점은 old, young 영역으로 나누지 않고 리전이라는 단위로 일정하게 나눠두는 것이다. (물론 거대 리전이라는게 존재한다)
그래서 liveness가 가장 적은(효율이 좋은) 부분을 gc 대상으로 판단한다.
물론 eden, survivor, old 영역등은 여전히 존재하며, 하나의 리전이 하나의 상태를 갖는다.
이 알고리즘의 목적은 매우 큰 메모리 크기에서도 아주 작은 GC타임을 유지하는 것이다.
따라서 64bit에서만 사용가능하다.
Colored pointers 와 Load barriers 라는 특이한 방법을 쓰고, 리전의 경우도 SMALL, MEDIUM, LARGE(제한없음) 이라는 세가지 타입이 존재한다.
내용이 어려워 완전히 이해는 못하였지만, 메모리 주소 공간의 특정 비트를 특정한 의미로 쓰고(Colored Pointer) 이를 활용해 메모리 컴팩션을 STW없이 진행하는게 큰 특징 인것 같다.
자세한 내용은 이 글의 범위를 벗어나므로, 생략한다.