JAVA/Beginning2009. 2. 16. 11:47

유닉스 서버나 윈도우 기반 서버든 GC를 수행하는 시점에서는 해당 WAS의 컨테이너에서
서비스가 처리되지 않는다. 즉 GC가 많이 발생하면 할수록 응답시간에 많은 영향을 끼친다는 것이다.
그래서 GC의 기본지식은 알고 있으면 도움이 된다.

GC란

Garbage Collection 이란 말 그대로 쓰레기를 정리하는 작업이다.
자바 프로그래밍에서 쓰레기란 객체이다. 하나의 객체는 메모리를 점유하고 필요하지 않으면
메모리를 해제해야 한다.

자바에선 개발자가 메모리를 처리하기위한 로직을 만들 필요가 없고, 절대 만들어서도 안된다.

GC의 원리

  • 메모리 할당
  • 사용중인 메모리 인식
  • 사용하지 않는 메모리 인식

사용하지 않는 메모리를 인식하는 작업을 수행하지 않으면 할당한 메모리 영역이 꽉차서 WAS에
행(Hang:서버가 요청을 처리 못하는 상태)이 걸리거나 더 많은 메모리를 할당하려는 현상이 발생할 것이다.

JVM의 메모리는 크게 클래스 영역, 자바스택, 힙, 네이티브 메소드 스택의 4개 영역으로 나뉘지만
힙영역만 고려한다.(GC는 힙영역에서만 발생한다.)

위의 그림에서도 Young 영역과 Old영역에만 집중하자.
Young 영역은 Eden 영역과 두개의 Survivor 영역으로 나뉘므로 우리가 고려해야 할 메모리 영역은
4개의 영역인 것이다.

메모리에 객체가 생성되면 Eden 영역에 객체가 지정된다.
Eden영역에 데이터가 어느정도 쌓이면 Survivor영역으로 옮겨지게 되는데 두개의 Survivor 영역중
우선순위가 있는 것은 아니다.

Eden영역의 객체와 어느한쪽에 할당된 Survivor 영역이 차면, GC가 되면서 Eden영역의 객체과
꽉찬 Survivor 영역의 객체를 비어있는 Survivor 영역으로 이동시킨다.
그러다가 더 큰 객체가 생성되거나 더이상 Young 영역에 공간이 남지 않으면 Old 영역으로 이동하게 된다.

GC의 종류

  • 마이너GC : Young 영역에 발생되는 GC
  • 메이저GC : Old영역이나 Perm영역에서 발생하는 GC

GC가 어떻게 상호 작용하느냐에 따라서 GC방식에 차이나 나며, 성능에도 영향을 준다.
GC가 발생하거나 객체가 각 영역에서 다른 영역으로 이동할때 애플리케이션의 병목이 발생하면서
성능에 영향을 주게 된다.

4가지 GC방식

  • Serial Collector (시리얼콜렉터)
  • Parallel Collector (병렬콜렉터)
  • Parallel Compacting Collector (병렬컴팩팅콜렉터)
  • Concurrent Make-Sweep(CMS) Collector (CMS컬렉터)

여기에 명시된 네가지 GC방식은 WAS나 자바 애플리케이션 수행시 옵션을 지정하여 선택할 수 있다.

시리얼 콜렉터

Young 영역과 Old 영역이 연속적으로 처리되며 하나의 CPU를 사용한다.
콜렉션이 수행될 때 애플리케이션 수행이 정지된다.

  1. 살아있는 객체들은 Eden영역에 있다.
  2. Eden영역이 꽉차면 To Survivor 영역으로 살아있는 객체들이 이동한다.
    Survivor영역에 들어가기 큰 객체는 Old 영역으로 이동한다. 그리고 From 영역의 살아있는
    객체는 To Survivor 영역으로 이동한다.
  3. To Survivor 영역이 꽉찼을 경우, Eden 영역이나 From 영역에 남아있는 객체는 Old영역으로 이동한다.

이후 Old영역이나 Perm 영역에 객채들은 Mark-Sweep-Compact 콜렉션 알고리즘을 따른다.
이 알고리즘은 간단하게 *안쓰는거 표시해서 삭제하고 한곳으로 모으는 알고리즘*이다.

  1. Old 영역으로 이동된 객체들 중 살아 있는 객체를 식별한다. (Mark)
  2. Old 영역의 객체들을 훑어보는 작업을 수행하여 쓰레기 객체를 식별한다. (Sweep)
  3. 필요없는 객체들을 지우고 살아있는 객체들을 한곳으로 모은다. (Compact)

이렇게 작동되는 시리얼 콜렉터는 일반적으로 클라이언트 종류의 장비에서 많이 사용한다.
즉 대기 시간이 많아도 크게 문제되지 않는 시스템에서 사용된다.
자바 옵션 : -XX:+UseSerialGC

병렬콜렉터

이 방식의 목표는 다른 CPU 대기 상태로 남아 있는 것을 최소화 하는 것이다. 시리얼 콜렉터와 달리
Young 영역에서 콜렉션을 병렬 처리한다.
많은 CPU를 사용하기 때문에 GC부하를 줄이고 애플리케이션의 처리량을 증가 시킬 수 있다.

Old 영역의 GC는 시리얼 콜렉터와 마찬가지로 Mark-Sweep-Compact 콜렉션 알고리즘을 사용한다.
자바 옵션 : -XX:+UseParallelGC

병렬컴팩팅콜렉터

Young 영역의 GC 처리는 병렬과 동일하지만 Old 영역의 GC는 다음 단계를 거친다.

  • 표시단계 : 살아 있는 객체 식별
  • 종합단계 : 이전의 GC를 수행하여 컴팩션된 영역에 살아 있는 객체의 위치 조사
  • 컴팩션단계 : 컴팩션 수행단계, 수행이후엔 컴팩션된 영역과 비어있는 영역으로 나뉜다.

병렬콜렉트와 동일하게 여러 CPU를 사용하는 서버에 적합하다.
자바옵션: -X:+UseParallelOldGC

CMS콜렉터

로우 레이턴스 콜렉터(low-latency-collector)로도 알려져 있으며 힙메모리 영역이
클때 적합하다. Young 영역에 대한 GC는 병렬콜렉터와 동일하다.
Old 영역의 GC단계

  • 초기표시단계 : 짧은 대기시간으로 살아 있는 객체를 식별
  • 컨커런트 표시단계 : 서부 수행과 동시에 살아있는 객체를 표시
  • 재표시 : 컨커런트 표시단계에서 표시하는 동안 변경된 객체를 다시 표시
  • 컨커런트 스윕단계 : 표시되어 있는 쓰레기를 정리

CMS콜렉터 방식은 2개 이상의 프로세서를 사용하는 서버에 적당하다.가장 적당한 대상으로
웹서버가 있다.

강제로 GC시키기

System.gc() 메서드나 Runtime.getRuntime().gc()메서드를 쓰면 되지만 완전비추!!!!

왜냐하면 GC를 수행하는 동안 다른 애플리케이션의 성능에 영향을 미친다는 점에서

단위:ms(밀리초, 1/1000초)

구분 응답시간
System.gc() 메소드포함 750ms~850ms
System.gc() 메소드미포함 0.13ms~0.16ms

비교해보면 소스하나에 포함된 gc()메서드 만으로 5000배의 성능차이를 보인다.
실제 운영중인 시스템에 이코드가 있으면 응답속도에 미치는 영향은 실로 엄청나게 커진다.

Posted by B정상