Skip to content

Latest commit

 

History

History
146 lines (84 loc) · 6.5 KB

Java Garbage Collection(GC).md

File metadata and controls

146 lines (84 loc) · 6.5 KB

Java Garbage Collection(GC)

Garbage란?

프로그램을 실행하다보면 Garbage 즉, 쓰레기가 발생하게 되는데 이는 쉽게 말하자면 정리되지 않은 메모리, 유효하지 않은 주소다.

int[] arr = new int[3];

arr[0] = 1;
arr[1] = 2;
arr[2] = 3;

arr = new String[3];

arr[0] = "Java";
arr[1] = "JavaScript";
arr[2] = "Node.js";

위의 코드를 보면 int타입의 배열 arr를 사용하다가 String타입의 배열을 만들고 arr가 이를 가리키도록 하고 있다.

여기서 처음 생성했던 int타입의 배열은 사용할 수 없는 메모리가 되고 이를 프로그래밍 언어로는 Dangling Object, 자바에서는 Garbage라고 한다.


GC(Garbage Collector)의 구조

Garbage Collector가 담당하는 메모리 영역은 JVM에서 Heap영역을 다룬다.

Young, Old, Permanent 세 영역으로 나뉘게 되며 이를 세분화 하면 총 4개의 영역으로 나뉘게 된다.

  • Young : Eden, Survivor
  • Old : Old
  • Permanent : Permanent(이하 Perm)

Perm 영역

Perm영역에서 담고 있는 정보는 다음과 같다.

  • Class 의 Meta정보
  • Method의 Meta 정보
  • Class와 관련된 배열 객체 Meta 정보
  • Static 객체
  • 상수화된 String 객체
  • JVM 내부적인 객체들과 JIT의 최적화 정보

프로젝트가 커지면 perm gen이 커서 에러가 나는데 이때 MaxPermSize 옵션을 JVM 옵션에 크게 주면 해결할 수 있다.

Java 8에서는 고질적인 perm gen space error를 해결하기 위해서 perm 영역을 없애버렸고 이에 따라 -XX:MaxPermSize 설정이 사라지고 -XX:MaxMetaspaceSize 로 바뀌게 되었다.


GC(Garbage Collector)의 작동 원리

GC의 역할의 공통적인 원리는 Heap내의 객체 중 Garbage를 찾아 이를 처리하고 메모리를 회수한다는 것이다.

이 과정에서 객체가 Garbage인지 아닌지를 판단하기 위해 reachability개념을 사용한다. 보통 하나의 객체는 다른 객체를 참조하고 그 객체는 또 다른 객체를 참조하게 되는데 여기서 최초에 참조한 객체를 Root Set이라고 한다.

java_gc_object

위의 그림과 같이 각각의 객체가 서로 참조하면서 참조 사슬이 형성되는데 Root Set에서 참조 사슬에 의해 Unreachable한 객체들은 Garbage Collection의 대상이 된다.


GC(Garbage Collector)의 종류

java_gc_heap

Garbage Collector는 크게 Minor GCMajor GC가 있다.


Minor GC

Minor GCYoung 영역에서 발생하는 GC다.

새롭게 생성된 객체는 주로 Eden영역에 위치하게 된다.
Eden영역에서 Garbage Collection이 발생하고 남은 객체는 Survivor영역으로 넘어가게 된다.
이 과정을 반복하게 되며 계속해서 남아 있는 객체는 Old영역으로 넘어간다.

이를 정리하면 다음과 같다.

  • 객체 생성 : Eden영역에 위치.
  • Garbage Collection 발생 : 남은 객체는 Survivor영역으로 이동.
  • 위 과정을 반복 : 계속해서 남아 있는 객체는 Perm영역으로 이동.

Major GC

Magejor GCOld 영역에서 발생하는 GC다. Old 영역의 데이터가 가득 찼을 때, 발생된다.

Old 영역에 있는 모든 객체들을 검사하여 참조되지 않고 있는 모든 객체들을 한 번에 삭제한다.
이 과정은 시간이 오래 걸리고 실행 중 프로세스가 정지된다.(Stop the world)

Major GC가 발생하면 GC를 실행하는 쓰레드를 제외한 나머지 쓰레드는 모두 작업을 멈춘다.


GC(Garbage Collection)의 방식

빈번한 Garbage Collection의 수행은 성능에 영향을 줄 수 있고 이 때문에 Garbage Collection의 수행 타이밍은 별도의 알고리즘을 기반으로 수행된다.


Serial GC

적은 메모리와 CPU의 코어 갯수가 적을 때 적합한 방식으로 운영 서버에서는 사용하지 않는 방식이다.

Young영역에서는 위에서 설명한 Minor GC에서 사용하던 방식을 사용하고 Old영역에서는 mark-sweep-compact라는 알고리즘을 사용한다.

  • Old 영역에서 살아있는 객체를 마크(Mark)한다.
  • Heap의 앞 부분부터 확인하여 살아 있는 것만 남긴다.(Sweep)
  • 각 객체들이 연속되게 쌓이도록 다시 Heap의 앞부분부터 채워 넣는다.(Compaction)

Parallel GC(Throuhput GC)

Serial GC와 기본적인 알고리즘은 같지만 GC를 처리하는 쓰레드가 여러 개다. 즉, 더 빠르게 Garbage Collection을 수행할 수 있다. 코어의 갯수가 많고 메모리가 충분하면 유리한 방식이다.

Parallel Old GC

JDK 5 update 6부터 제공한 GC 방식이다. 이름에서 알 수 있듯이 Parallel GC와 비교하면 Old영역에서 알고리즘이 다르다. Mark-Summary-Compaction이라는 알고리즘을 사용하는데 Sweep 단계가 아닌 Summary 단계를 거치게 된다.

Summary 단계는 앞서 GC를 수행한 영역에 대해서 별도로 살아 있는 객체를 식별하며 좀 더 복잡한 단계를 거친다.

Java 7 Update 4 이후부터는 XX:+UseParallelGC 사용시에도 -XX:+UseParallelOldGCdefault로 사용하게 된다.
Java 7 Update 4 이상이면 UseParallelGCUseParallelOldGC 중 어느 하나만 사용해도 결국 UseParallelOldGC 처럼 동작한다.
-XX:+UseParallelGC만 쓰면 되고, UseParallelOldGC에 의해 수행되었던 역할을 굳이 끄고 싶을 때만 XX:-UseParallelOldGC을 사용하라고 한다.


Parallel vs CMS

  • Parallel은 최대 처리량을 위한 GC 방식이며 Mark, Sweep, Compaction 단계가 동시에 일어나기 때문에 상대적으로 멈춤(pause) 시간이 크다.

  • CMSFull GC시 멈춤 시간이 짧은 편이지만 Parallel에 비해 처리량이 적고 더 많은 자원을 사용한다.



Reference