GC(Garbage Collection)

도도새·2025년 2월 14일

자바 청소부

얼마전 야심차게 샀던 "JVM 밑바닥까지 파헤치기 -저우즈밍 저"가 계속 눈에 밟혀 출퇴근시간에 읽고 있습니다. (어려운 부분은 건너띄고 있어요..) 솔직히 도움이 될까 싶었는데, 생각보다 재밌는 부분이 많아 어찌저찌 마지막장을 읽고 있습니다.
다름이아니라 최근 CS를 다시 공부하면서 예전에 정리해놓은 CS 면접 답변을 보니, GC에 대한 설명이 다소 부족했다는 생각이 들었습니다.
물론 <<자바 가상명세>>에 대해 완전히 이해하지 못했고, 이해했다고 생각했던 부분 또한 거짓 이해라고 생각되지만 아무렴 재미만 있다면 괜찮지 않을까하는 생각해 책을 참고해 수정해볼까 합니다.

Garbage Collection

앞서 말씀드리고 싶은점은 책을 참고했으나, 작성 중 잘못된 정보가 있을 수 있습니다. 꼭 스스로 확인해보세요!

첫번째

이전에 작성해놨던 GC에 대한 면접 답변입니다.

가바지 컬렉션이란?
메모리 중 더 이상 사용되지 않는 부분을 자동으로 회수하는 메모리 관리 기법입니다. GC는 크게 young, Old 두 영역으로 나뉘며 객체가 처음 생성될 시 Young 영역으로 할당됩니다.

최근 사수가 "객체를 메모리에서 해제하려면 어떻게 하는지 아나요?"라는 질문에 'GC가 관리하는거 아녀?' 라고 생각하며 쳐다보니 "null 선언을 해주면 해제하잖아요" 라고 했었습니다.

기억 저편에 자바 책에서 해당 내용을 읽었던 기억이 나며
"그럼 명시적으로 null을 계속 선언해주는게 좋은건가?"라는 의문에 빠질때쯤, 해당 책에서 관련 내용이 나왔습니다.

-JVM 밑바닥까지 파헤치기 409p 중

... 이따금 시간을 많이 소모하는 동작에 앞서 메모리를 대량 점유하는 변수에 수동으로 null을 할당하는 코드를 볼 수 있다. (생략) 변수 슬롯의 기존 정보를 삭제하는 형태다.
(생략) 한때 어떤 자바책에서는 구체적인 설명 없이 '사용하지 않는 객체에는 수동으로 null을 할당하라'는 규칙을 권장하였다 (생략) 나는 이 규칙에 동의하지 않는다.
첫째, 변수 범위를 적절히 지정하여 변수가 회수되는 시간을 제어하는게 가장 우아한 해법이다. (생략) 이때 JIT 컴파일러는 null 할당을 잘못된 작업으로 판단하여 무시할 가능성이 매우 높다.

너무 길지만 간략하게 말하면, 바이트코드 실행 엔진의 개념 모델을 이해하는 사람끼리만 의미가 통할 뿐 다소 모호해질 수 있으며, JIT 컴파일러가 이를 적용하지 않는 경우도 발생할 수 있다는 것입니다.

즉, 수동으로 해제하려는 것보다 GC가 적절히 회수할 수 있도록 잘 작성하는 것이 중요하다는 의미라고 생각합니다.

두번째

가비지 컬렉션 동작 흐름을 설명해주세요
처음 생성된 객체는 Eden 영역에 위치하며, 영역이 가득차면 Full GC로 Minor GC가 발생하게 되는데 자주 사용되는 객체는 Survivor 영역으로 이동하게 됩니다. 최종적으로 살아남은 객체는 Old 영역으로 이동하며 Old 영역또한 가득찰 경우 Major GC가 발생하여 객체를 제거합니다.

이번 질문은 가비지 컬렉션 동작에 대한 답변입니다. 물론 전체를 다 외우진 않았었고, 대충 흐름만 외웠었을때

Eden -> Full GC(Minor GC) -> Survivor 1 or 2 -> old -> Full (Major GC)
* 이과정에서 Mark and Sweep이 발생합니다.

으로 이해했었습니다. 책에서의 내용 또한 해당 내용으로 설명하고 있습니다. 다소 다른점이라면 최근 사용되고 있는 GC인 G1과 ZGC의 동작 방식은 다소 다른점이라는 것입니다.
기본 근간은 동일한 Eden으로 이동하고 Survivor로 이동하며 old로 이동하는 것 또한 동일하지만, 큰 차이점은 아래와 같습니다.

  1. Survivor 1 or 2의 공간을 따로 분리하지 않습니다.
  2. Full GC가 발생해야 GC가 동작하는 것이 아닌, 특정 주기를 가지며 동작합니다.
  3. Eden과 Survivor 뿐만 아니라 Old 또한 감시 대상이 됩니다.
  4. mark-and-Sweep 방식이 아닌, Mark-Compact 방식입니다.

근간은 동일하다지만 제가 느끼기엔 그저 이름만 동일한 GC라고 생각이 들었습니다. 성능 또한 대폭 향상 됐는데, "그럼 무조건 G1과 ZGC를 써야겠구만?!" 이라고 생각할 찰나, 역시나 저의 알량한 마음을 꿰뚫고 있었던 저자가 이 또한 설명해줍니다.

... 가비지 컬렉터 중 선택해야 하는 독자들을 위해 오라클은 다음과 같이 안내하고 있다.
- 최대 100MB 정도의 작은 데이터를 다룬다면 -> 시리얼 컬렉터
- 애플리케이션이 단일 프로세서만 사용하고 일시 정지 시간 관련 제약이 없다면 -> 시리얼 컬렉터
- 애플리케이션의 최대 성능이 가장 중요하고, 지연 시간 관련 제약이 없거나 1초 이상의 지연 시간도 허용된다 -> 기본 또는 패러럴 컬렉터
- 처리량보다 응답 시간이 중요하고 일시정지가 짧아야한다 -> G1
- 응답 시간이 매우 중요하다 -> ZGC

마치며

책에서 더 많은 내용을 다루고 있지만, 이 이상 다루게 된다면 잘못된 정보를 전달하게 될까 두려워 아는 범위 내에서만 작성해봤습니다....
JVM을 굳이 알아야 되나? 라고 생각했지만 읽으면 읽을수록 생각보다 나와 가까이 있었구나.. 라고 깨닫게 되는 책인것 같습니다.
음... 새해복 많이받으세요!

profile
깃허브 : https://github.com/YoHanKi

0개의 댓글