가비지 컬렉터란 (역할)
자바의 메모리 관리 방법 중의 하나로 JVM의 Heap 영역에서 동적으로 할당했던 메모리 영역 중 필요 없게 된 메모리 영역을 주기적으로 삭제하는 일을 한다.
C나 C++에서는 가비지 컬렉터가 없어 프로그래머가 수동으로 메모리 할당과 해제를 일일이 해줘야 하는 반면 Java는 JVM에 탑재되어 있는 가바지 컬렉터가 메모리 관리를 대행해 주기 때문에 개발자 입장에서 메모리 관리, 메모리 누수 문제에 대해 완벽하게 관리하지 않아도 되어서 오롯이 개발에만 집중할 수 있다.
더 이상 필요 없어진 메모리를 쓰레기(Garbage)라고 하고 이 쓰레기를 효과적으로 처리하는 작업을 GC(Garbage Collection)이라고 부른다.
단점
- 메모리가 언제 해제되는지 개발자가 정확히 알 수 없다.
- 가비지 컬렉터가 동작하는 동안에는 다른 동작을 멈추기 때문에 오버헤드가 발생한다.
가비지 컬렉터의 원리
GC작업을 하는 가비지 컬렉터는 다음과 같은 일을 한다.
- 메모리 할당
- 사용 중인 메모리 인식
- 사용하지 않는 메모리 인식
가리키는 변수가 없는 메모리 영역을 수집하고 그 메모리 연역의 해제를 자동으로 해준다.
아래의 코드를 보자
Vehicle vehicle = new Vehicle("bus");
on(vehicle);
vehicle = null;
new Vehicle("bus");를 통해 메모리 어딘가에 할당이 되었을 것이다. 그리고 필요한 곳에 쓰인 뒤 해당 메모리 영역을 가리키던 "vehicle"이 null 이 되었다.
이럴 때 가비지 컬렉터가 new Vehicle("bus")를 메모리 해제를 한다.
위 사진과 같이 어떤 것도 참조되고 있지 않은 2번의 객체는 참조되고 있지 않은 상태이기 때문에 GC의 대상이 된다.
JVM메모리에서는 객체들은 실질적으로 Heap 영역에서 생성되고 Method Area이나 Stack Area에서는 Heap Area에 생성된 객체의 주소만 참조하는 형식으로 구성된다.
하지만 이렇게 생성된 Heap Area의 객체들이 메서드가 끝나는 등의 특정 이벤트들로 인하여 Heap Area 객체의 메모리 주소를 가지고 있는 참조 변수가 삭제되는 현상이 발생하면, 위의 그림에서의 빨간색 객체와 같이 어디서든 참조하고 있지 않은 객체(Unreachable)들이 발생하게 된다.
이러한 객체들을 주기적으로 가비지 컬렉터가 제거해 준다
가비지 컬렉터가 사용하는 알고리즘
GC를 수행하기 위해 Stop The World가 발생되고 이 때문에 애플리케이션이 중지되는 문제점이 발생하게 되었다.
또한 자바가 발전됨에 따라 Heap의 사이즈가 커지면서 애플리케이션의 지연 현상이 두드러지게 되었고, 이를 최적화하기 위해 다양한 알고리즘이 개발되었다.
Stop The World (STW)
GC를 수행하기 위해 JVM이 프로그램 실행을 멈추는 현상을 의미.
GC가 작동하는 동안 GC 관련 Thread를 제외한 모든 Thread는 멈추게 되어 서비스 이용에 차질이 생길 수 있다.
상황에 따라 필요한 GC방식을 설정해서 사용할 수 있다.
Serial GC
- 서버의 CPU 코어가 1개일 때 사용하기 위해 개발된 가장 단순한 GC
- GC를 처리하는 쓰레드가 1개 이어서 가장 STW 시간이 길다.
- 보통 실무에서 사용하는 경우는 없다.
Parallel GC
- Java 8의 디폴트 GC
- Serial GC와 기본적인 알고리즘은 같지만, Heap의 Young 영역의 Minor GC를 멀티 쓰레드로 수행 (Old 영역은 여전히 싱글 쓰레드)
- Serial GC에 비해 STW 시간 감소
Young 영역 (Minor GC)
Heap에는 두 개의 영역이 있는데, 이 중 Young Generation(Young 영역)에는 새롭게 생성된 객체가 할당되는 영역이다.
대부분의 객체가 금방 Unreachable(참조 X) 상태가 되기 때문에 많은 객체가 Young 영역에 생성되었다가 사라지는데, Young 영역에 대한 가비지 컬렉션을 Minor GC라고 부른다.
Old 영역 (Major GC)
Young 영역에서 오랫동안 살아남은 객체들이 복사되는 영역인 Old Generation(Old 영역)이 있다.
Young 영역보다 크게 할당되면, 영역의 크기가 큰 만큼 가비지는 적게 발생한다.
Old 영역에 대한 가비지 컬렉션을 Major GC (또는 Full GC)라고 부른다.
Eden, Survival
더 효율적인 GC를 위해 Young 영역을 3가지 영역(Eden, survivor 0, survivla 1)으로 나눈다.
Eden : new를 통해 새로 생성된 객체가 위치. 정기적인 쓰레기 수집 후 살아남은 객체들은 Survivor 영역으로 보냄
Survival 0 / 1 : 최소 1번의 GC 이상 살아남은 객체가 존재하는 영역. 특별한 규칙이 있는데 0 / 1 둘 중 하나는 꼭 비어있어야 한다.
CMS GC (Concurrent Mark Sweep)
- 애플리케이션의 쓰레드와 GC 쓰레드가 동시에 실행되어 STW 시간을 최대한 줄이기 위해 고안된 GC
- 단, GC 과정이 매우 복잡해짐
- GC 대상을 파악하는 과정이 복잡한 여러 단계로 수행되기 때문에 다른 GC 대비 CPU 사용량이 높다.
- 메모리 파편화 문제
- Java 9부터 deprecated 되었고 Java 14에서는 사용이 중지
G1 GC (Garbage First)
- CMS GC를 대체하기 위해 jdk 7에서 최초로 release 된 GC
- Java 9+ 버전의 디폴트로 지정
- 기존의 GC 알고리즘에서는 Heap 영역을 물리적으로 고정된 Young / Old 영역으로 나누어 사용하였지만, G1 GC는 아예 이러한 개념을 뒤엎는 Region이라는 개념을 새로 도입하여 사용.
- 전체 Heap 영역을 Region이라는 영역으로 체스같이 분할하여 상황에 따라 Eden, Survivor, Old 등 역할을 고정이 아닌 동적으로 부여
- Garbage로 가득 찬 영역을 빠르게 회수하여 빈 공간을 확보하므로, 결국 GC 빈도가 줄어든 효과를 얻게 되는 원리
Shenandoah GC
- Java 12에 release
- 레드 햇에서 개발한 GC
- 기존 CMS가 가진 단편화, G1이 가진 pause의 이슈를 해결
- 강력한 Concurrency와 가벼운 GC 로직으로 heap 사이즈에 영향을 받지 않고 일정한 pause 시간 소요가 특징
ZGC (Z Garbage Collector)
- Java 15에 release
- 대량의 메모리를 low-latency로 잘 처리하기 위해 디자인된 GC
- G1의 Region처럼, ZGC는 ZPage라는 영역을 사용하며, G1의 Region은 크기가 고정인데 비해, ZPage는 2mb 배수의 동적으로 운영됨
- ZGC가 내세우는 최대 장점 중 하나는 힙 크기가 증가하더라도 STW의 시간이 절대 10ms를 넘지 않는다는 것
참고
항해 개발자 취업 리부트 코스를 수강하고 작성한 콘텐츠 입니다.
IT 커리어 성장 코스 항해99, 첫 취업부터 현직자 코스까지
항해99는 실무에 집중합니다. 최단기간에 개발자/PM으로 취업하고, 현직자 코스로 폭발 성장을 이어가세요. 실전 프로젝트, 포트폴리오 멘토링, 모의 면접까지.
hanghae99.spartacodingclub.kr
'멋진 개발자 > Java & Spring' 카테고리의 다른 글
[항해 취업코스] 개발자 취준 기록 12 - DI와 IoC (0) | 2024.03.07 |
---|---|
[항해 취업코스] 개발자 취준 기록 11 - Java Map 내부 구현 파악 (1) | 2024.03.07 |
[항해 취업코스] 개발자 취준 기록 9 - 클래스와 인스턴스의 차이 (feat. 객체) (0) | 2024.03.06 |
[항해 취업코스] 개발자 취준 기록 8 - JVM의 스택과 힙 메모리 영역 (0) | 2024.03.06 |
[항해 취업코스] 개발자 취준 기록 7 - 동시성 이슈 해결 방법 (1) | 2024.03.06 |