본문 바로가기
언어/JAVA

[JAVA] Garbage Collection (GC)

by 이민우 2021. 3. 30.
728x90
반응형

자바의 코드와 C 계열 언어들의 코드를 비교해보면, C 계열 언어는 클래스 선언 시 생성자와 소멸자를 정의해주지만, 자바의 경우에는 생성자만 정의하곤 한다.

 

이러한 차이점은 C 계열 언어들과 달리 자바에서는 개발자가 굳이 메모리를 해제하지 않아도 되기 때문이다. 그 이유는 GC 때문이다.

 

JVM의 GC는 더 이상 사용되지 않는 인스턴스를 찾아 메모리에서 삭제하는 역할을 수행한다.

 

GC는 메모리의 힙 영역을 돌아다니며 더 이상 사용되지 않는 인스턴스에 할당된 메모리를 삭제하는데, 이를 위해 자바는 GC를 실행하기 위해 GC의 쓰레드를 제외한 다른 쓰레드들을 전부 잠시 멈추었다가, GC의 동작이 완료된 이후 재개해야 한다. 이러한 동작을 Stop the World 라고 한다.

 

Stop The World는 당연히 시스템에 큰 영향을 줄 수 밖에 없다. 본인을 제외한 모든 쓰레드들을 잠시 일시정지 시켜버리니 당연한 것이다. 이러한 성능 저하를 줄이기 위해 GC 튜닝을 진행하는데, 이는 stop-the-world의 시간을 줄임으로써 성능 저하를 줄이는 역할을 한다.

 

 

GC는 JVM의 네 개의 메모리 영역 중 힙 영역의 메모리 내에서 동작한다.

JVM의 힙 영역은 크게 세 영역으로 나뉜다. Young 영역, Old 영역, Perm 영역(현재는 MetaSpace 영역)이다.

 

Young 영역에는 새롭게 생성한 객체가 위치한다. 하지만 대부분의 객체가 금방 unrechable(접근 불가 상태)가 되어 사라지고, 그렇지 않은 객체들은 Old 객체로 복사된다.

 

Perm 영역은 메소드 영역이라고도 부른다. 단어 그대로 영구적으로 존재할 객체들이 저장되는 메모리이다. 주로 자바의 클래스나 스트링 객체들이 위치한다. static 키워드로 생성한 객체들이 대부분 여기에 저장되는데, 종종 생각없이 static 키워드를 과다하게 사용하면 이 영역이 가득 차버리는 현상인 Out Of Memory가 발생했다. 또한 런타임 중 사이즈 조절이 불가능했다.

 

이러한 단점으로 JDK 8부터는 Perm 영역이 사라지고 Metaspace가 그 자리를 대신하게 되었는데, 이 공간은 OS가 자동으로 크기를 조절함으로써 OOM의 가능성을 줄였다.

 

 

GC의 방식으로는 크게 다섯 가지가 존재한다.

1) Serial GC

-Old 영역의 객체를 mark 하고 힙의 앞부분부터 살아있는 객체를 sweep한 뒤 힙의 앞부분부터

 객체를 쌓는(Compact) mark-sweep-compact 알고리즘을 사용한다.

-메모리와 CPU 코어 수가 적을 때 사용하면 좋다.

 

2) Parallel GC

-Serial GC와 기본적인 알고리즘은 같지만, GC를 여러 개의 쓰레드가 처리한다.

-그렇기에 메모리와 CPU 코어 수가 많을수록 좋다.

 

3) Parallel Old GC

-Parallel GC와 같지만 Old 영역에서만 Mark-Summary-Compact 알고리즘을 사용한다.

 

4) CMS GC

-Stop the world 이후 Initial marking 시 살아있는 객체만 검색한다.

-그리고 concurrent mark 단계에서 새로 추가되거나 참조가 끊긴 객체들을 remark 한다.

-모든 작업이 멀티 스레드 환경에서 동시진행되기에 stop the world 시간이 매우 짧은 대신 많은

 메모리와 CPU가 필요하고, Compact 단계가 제공되지 않는다.

 

5) GI GC 

-Young, Old 영역 없이 매우 빠르게 객체를 할당하고 회수한다.

728x90
반응형

'언어 > JAVA' 카테고리의 다른 글

[JAVA] Call by Value & Call by reference  (0) 2021.04.29
[JAVA] == vs equals vs hashCode  (0) 2021.03.30
[JAVA] String, StringBuffer, StringBuilder  (0) 2021.03.30
[JAVA] BufferedReader와 Scanner  (0) 2021.03.30
HashSet  (0) 2020.10.27