본문 바로가기

Programming Language/Java & Scala

자바 가비지 컬렉션 설명 및 종류

Getting Started

JVM 기반 언어와 C, C++과 가장 큰 다른점은 free()와 같은 메모리접근을 통한 명시적 메모리 해제 여부이다. 자바는 OS메모리 영역에 직접 접근하지 않고 JVM이라는 Process이자 가상머신을 통해 접근한다. 
자바 application은 System.gc()와 같은 명시적 명령어를 통해 garbage collection을 수행할 수 있으나, 권장되지 않는다. 대신 JVM의 옵션에 따라 Serial GC, Parallel GC, CMS(Concurrent Mark Sweep) GC, G1 GC(after java 7)이 사용되고, 각 GC들은 특정 알고리즘과 주어진 옵션에 따라 메모리 관리를 하게 된다.

What is garbage?

Java application에서는 가비지 컬렉션을 통해 더이상 사용되지 않는 오브젝트들을 제거한다. 가비지 컬렉션에서 '더이상 사용되지 않는'의 의미는 'Unreachable object'라고 말할 수 있다. Unrechable object들은 Stack에 도달할 수 없는 Heap영역의 객체단위라고 할수 있다.

Unreachable object

Java application에서 unreachable object를 보여주는 예제를 아래에서 확인해보자.


Integer i = new Integer(4);
// 레퍼런스변수 i는 새로운 Integer 객체 인스턴스를 가르킨다.
i = null;
// 레퍼런스변수 i는 null로 할당됨
// 이전에 만든 Integer객체 인스턴스는 unrechable object가 된다.

heap memory 영역에 object가 선언된 이후 i에 null이 선언되면서 Integer(4)는 어느 누구도 참조하지 않는 unreachable object가 되었다. 이 object는 곧 JVM의 GC에 의해 반환된다.


Garbage Collections 과정

가비지 컬렉션의 과정에 대해 확인해보자.
참고로 C언어와는 다르게, deallocating memory과정은 가비지 컬렉터에 의해 자동으로 실행된다.

Step 1: Marking

가비지 컬렉터는 메모리에서 live object를 확인 하고, unrechable object가 무엇인지 마킹하는 절차를 진행한다.

Step 2: Normal Deletion

가비지 컬렉터는 unrechable object를 삭제한다.

Step 2a: Deletion with Compacting

가비지 컬렉터중 일부는 memory를 더욱 효과적으로 쓰기위해  unreachable object를 삭제함과 동시에 압축을 진행하기도 한다.

Java Garbage Collection 용어 정리

# Young Generation : 최초로 new object가 생성되었을 경우 heap memory에서 위치하는 공간. MinorGC가 발생하면 unreachable object는 삭제되고, surviving object(참조되고 있는 객체들)은 Old generation으로 이동한다.
# Old Generation : Long surviving object들이 머무는 공간. Old generation이 가득차게되면 MajorGC가 발생한다.
# MinorGC : Young generation에서 발생하는 GC
# MajorGC : Old Generation에서 발생하는 GC
# Full GC : Heap memory전체를 clear하는 작업
# Stop the World Event : MinorGC 발생시 Stop the world event가 발생한다. MinorGC를 수행할때는 모든 application thread가 중지하고, 예외는 없다.
# Permanent generation : Java application에 필요한 클래스의 메타데이터를 자장하는 곳. Java8을 기준으로 Permanent generation은 heap memory가 아닌 native memory로 관리됨.(참고문서 : Java8에서 permSize를 대체하는 옵션?)

Java Garbage Collector의 종류

Serial GC

-XX:+UseSerialGC
MinorGC, MajorGC 모두 순차적으로 수행, Deletion and Compacting 수행

Parallel GC

-XX:+UseParallelGC
여러 CPU를 효과적으로 활용하기 위해 GC수행시 멀티스레드를 사용. Default로 young generation에서만 멀티스레드를 활용하나, 옵션을 통해 old generation에서도 멀티스레딩 활용가능. Deletion and Compacting 수행

CMS(Concurrent Mark Sweep) Collector

-XX:+UseConcMarkSweepGC
가비지 컬렉션 작업을 애플리케이션 스레드와 동시 수행. stop-the-world시간 최소화. Compacting수행하지 않아서 memory를 더 많이 차지.

G1 Garbage Collector

-XX:+UseG1GC
Java7부터 사용가능. 여러 CPU와 아주 큰 memory에서 효과적인 GC를 활용하기 위함. Oracle문서에 따르면 heap size가 6GB보다 클 경우 GC의 latency를 0.5sec이하로 낮출수 있다고 한다.(Oracle G1 GC문서) Java9에서는 default GC로 설정되어 있다.(이전까지는 Parallel GC가 default)

Oracle에서 G1 GC를 사용을 권하는(Recommend) 기준

# Full GC durations are too long or too frequent. 

# The rate of object allocation rate or promotion varies significantly. 

# Undesired long garbage collection or compaction pauses (longer than 0.5 to 1 second)


※ 일부 사진 및 내용은 Oracle Garbage collection Basics 공식문서에서 가져왔습니다.