레퍼런스 : http://gosilkroad.com/30000025219


GC (Gabage Collector)

Sun JVM 의 Heap Memory 영역은 다음과 같은 구조를 가진다.

 

[ Sun MicroSystems Memory 구조도 ]

위의 그림을 보면 메모리 영역은 다음과 같이 커다랗게 3부분으로 나뉘어진다.

1. Young Area
   - Eden
   - Survivor Spaces 2 block (S0, S1)
   - Virtual
2. Tenured Area (Old Area 라고도 부른다.)
   - Tenured
   - Virtual
3. Permanent Area
   - Perm
   - Virtual

* 보통 메모리를 명확하게 java -Xms1024m -Xmx1024m -XX:MaxPermSize=128m 형식으로 할당하기 때문에
  Virtual 영역은 없다고 보면 된다.

Java 실행시 Heap Size 를 주게되는데 설정된 Heap Size 를 설정된 Ratio 별로 나누어서 할당하게된다.
(Ratio 중에는 Young : Tenured 영역 분할 Ratio, Young 중에서 Eden : Survivor 영역 Ratio 가 있다.
자세한 사항은 이번 글에서는 넘어간다. -_-;)

그럼 위의 3가지 영역을 설명하면서 GC 되는 절차를 알아보자.

1. Young Area
 보통 객체 생성시 new 라는 keyword 를 이용하는데 이때 객체가 생성되는 부분이 Young 의 Eden 부분이다.
 Eden 부분에 객체가 생성되면서 메모리를 할당받게 되고 Eden Area 의 설정된 % 이상으로 메모리가 할당되면
 Young GC 가 일어나게 된다. (GC 의 종류도 참 많다. --;)
 이때 Young GC 가 일어나면 어떤 현상이 벌어지는지 눈 똑바로 뜨고 글을 읽어라.
 
 - Young GC
 Survivor 영역은 그림에서 보면 두개로 나뉘어져 있다. 각각을 S0, S1 이라 부른다.
 Eden 의 설정치 만큼 메모리가 할당되게 되면 Young GC 가 일어나는데 Young GC 란 Eden + S0 (처음 Young GC 일때)
 의 영역을 GC 를 실행한다. 이때 GC 대상에 포함되지 않는 (즉, Reference 가 살아있는 객체) 객체는
 S1 영역으로 옮겨지고 나머지 Week Reference 객체는 GC 된다.
 그후 다시 Eden 에 객체가 생성되고 메모리가 또 차게되면 이번에는 Eden + S1 이 GC 의 대상이고 이때 동일하게
 Reference 가 살아있는 객체는 S0 영역으로 옮겨지고 나머지 Week Reference 는 GC 된다.
 
 그럼 이말을 잘 풀어서 보면, Eden 은 무조건 GC 대상이고 Survivor 의 두 Area 가 돌아가면서 GC 대상이 되는것이다.
 Young GC 가 될때는 Eden + Survivor Area 중 한곳의 메모리를 전부 비우게 되며 Refrence 가 남아있는 객체를 다른 한곳의
 Survivor Area 로 할당하게 되는것이다. 즉, Survivor Area 의 S0 or S1 둘중에 한곳은 항상 비어있다고 보면 된다.
 
 그럼 Singleton Pattern 형식처럼 항상 메모리에 상주하게 구현한 객체들은 S0 와 S1 사이를 왔다리 갔다리 한다는 말인가?
 흠... -_-;
 정답은 안그렇다.
 
 java option 에 TenuringThreshold (default 32) 값에 의해서 S0, S1 을 몇번이상 왔다리 갔다리하면 이것은 오래 남을 객체라
 판단하고 Tenured Area (Old Area) 으로 보내진다.
 또한 Eden 10M, S0 1M, S1 1M 라고 했을때 Young GC 가 Eden + S0 가 일어날때 GC 후의 값이 5M 라면 어떻게 될까?
 정답은 S1 에 1M 를 할당하고 남은것은 Tenured Area 로 보내진다.

2. Tenured Area
 Old Area 라고도 부르며 Young Area 에서 넘어온 객체들이 할당되어진다.
 Tenured Area 역시 설정된 % 이상으로 메모리가 할당되면 GC 가 일어나게 되는데 이것이 Old GC 이다.
 Old GC 가 일어나도 Old 영역이 줄어들지 않는다면 Full GC 가 일어날 수 있으며 Memory Leak 을 생각해 볼 수 있다.

3. Permanent Area
 Permanent Area 는 Class 를 Loading 하는데 사용한다. 보통 Perm Size 는 64 이며 크게 잡을경우 128 을 잡기도 한다.
 개발 환경에서는 Hot Deploy 가 편하지만 운영환경이라면 Hot Deploy 하는것이 좋지않다.
 Hot Deploy 하게되면 Permanent Area 로 Class 가 Loading 되게되며, 기존의 Loading 되어있던 Old version 이 바로 Unloading 되는것은
 아니기 때문이다. (Permanent Area 의 경우 GC 라 하지않고 Unloading 이라 부른다.)
 문제는 수행중에 필요에 의해서 Unloading 이 발생하게 되는데 수시로 Hot Deploy 가 일어나서 Permanent Area 가 Full 나게되면
 Full GC 가 일어나게 된다.
 Loading 해야될 Class 보다 적은 Permanent Size 를 할당할 경우 Full GC 도 수시로 일어나지만 OOME (Out Of Memory Error) 가
 발생하며 WAS 가 down 될 수도 있다.
 

** Full GC 란 ?
 Old GC 후에 Tenured Area 이 줄어들지 않았을 경우 발생 할 수 있으며 또한 Permanent Area 가 Full 나면 일어난다.
 Full GC 가 일어나면 보통 수초에서 수십초의 시간을 소요하게 되며, 이때 JVM 은 Full GC 이외의 일은 하지 않는다.
 즉, 일반 상용 사이트의 Web Application Server 가 Full GC 가 일어나면 수초에서 수십초간 WAS 가 정지되는
 상황에 놓이는 것이다. 그러나 사이트가 정지되는 일은 별로 일어나지 않는데 이유는 일반 상용 사이트는 HA (High Availibilty)
 구성을 해놓기 때문에 한쪽 WAS 가 먹통이 되면 L/B (Load Balancer) 가 알아서 Load Banlancing 을 하게됨으로 일반 Client 가 사용하기에는
 아무런 문제가 발생하지 않는다.

 Full GC 가 일어난다는 것은 메모리 할당이 잘못됐거나, Memory Leak 발생하거나 하는 경우이므로 튜닝 포인트를 찾아내야한다.

Posted by 서오석
,